【发布时间】:2021-07-30 19:02:15
【问题描述】:
我在 c# 中使用这个 winapi 库并尝试用它创建一个屏幕截图应用程序。它与普通的winapi完全相似。问题是即使我正在更新窗口,油漆也只会发生一次。我曾经在 c++ 中使用过 winapi,遇到了完全相同的问题,但我似乎找不到解决方案。有谁知道这是什么问题? 谢谢!
internal class Program
{
static public int virtualScreenLeft = User32Methods.GetSystemMetrics(SystemMetrics.SM_XVIRTUALSCREEN);
static public int virtualScreenTop = User32Methods.GetSystemMetrics(SystemMetrics.SM_YVIRTUALSCREEN);
static public int virtualScreenRight = User32Methods.GetSystemMetrics(SystemMetrics.SM_CXVIRTUALSCREEN);
static public int virtualScreenBottom = User32Methods.GetSystemMetrics(SystemMetrics.SM_CYVIRTUALSCREEN);
static public int virtualScreenWidth = virtualScreenRight - virtualScreenLeft;
static public int virtualScreenHeight = virtualScreenBottom - virtualScreenTop;
static public bool mousePressed = false;
static public NetCoreEx.Geometry.Point lastMousePos = new NetCoreEx.Geometry.Point();
static public NetCoreEx.Geometry.Point currentMousePos = new NetCoreEx.Geometry.Point();
static public NetCoreEx.Geometry.Rectangle rect = new NetCoreEx.Geometry.Rectangle();
static public IntPtr bmp = captureVirtualScreen();
static IntPtr captureVirtualScreen()
{
// Get a DC compat. w/ the screen
IntPtr hdc = Gdi32Methods.CreateCompatibleDC(IntPtr.Zero);
// Make a bmp in memory to store the capture in
IntPtr bitmap = Gdi32Methods.CreateCompatibleBitmap(User32Methods.GetDC(IntPtr.Zero) ,
virtualScreenWidth, virtualScreenHeight);
// Join them
Gdi32Methods.SelectObject(hdc, bitmap);
// Copy from the screen to my bitmap
Gdi32Methods.BitBlt(hdc, virtualScreenLeft, virtualScreenTop,
virtualScreenWidth, virtualScreenHeight,
User32Methods.GetDC(IntPtr.Zero), 0, 0, BitBltFlags.SRCCOPY);
// Delete the DC
Gdi32Methods.DeleteDC(hdc);
// Return the bitmap
return bitmap;
}
static int Main(string[] args)
{
var instanceHandle = Kernel32Methods.GetModuleHandle(IntPtr.Zero);
var wc = new WindowClassEx
{
Size = (uint)Marshal.SizeOf<WindowClassEx>(),
ClassName = "MainWindow",
CursorHandle = User32Helpers.LoadCursor(IntPtr.Zero, SystemCursor.IDC_ARROW),
IconHandle = User32Helpers.LoadIcon(IntPtr.Zero, SystemIcon.IDI_APPLICATION),
Styles = WindowClassStyles.CS_HREDRAW | WindowClassStyles.CS_VREDRAW,
BackgroundBrushHandle = new IntPtr((int)StockObject.WHITE_BRUSH),
WindowProc = WindowProc,
InstanceHandle = instanceHandle
};
var resReg = User32Methods.RegisterClassEx(ref wc);
if (resReg == 0)
{
Console.Error.WriteLine("registration failed");
return -1;
}
var hwnd = User32Methods.CreateWindowEx(WindowExStyles.WS_EX_LEFT,
wc.ClassName, ";)", WindowStyles.WS_POPUP | WindowStyles.WS_VISIBLE,
virtualScreenLeft, virtualScreenTop,
virtualScreenWidth, virtualScreenHeight,
IntPtr.Zero, IntPtr.Zero, instanceHandle, IntPtr.Zero);
if (hwnd == IntPtr.Zero)
{
Console.Error.WriteLine("window creation failed");
return -1;
}
User32Methods.ShowWindow(hwnd, ShowWindowCommands.SW_SHOWNORMAL);
User32Methods.UpdateWindow(hwnd);
Message msg;
int res;
while ((res = User32Methods.GetMessage(out msg, IntPtr.Zero, 0, 0)) != 0)
{
User32Methods.TranslateMessage(ref msg);
User32Methods.DispatchMessage(ref msg);
User32Methods.UpdateWindow(hwnd);
}
return res;
}
private static IntPtr WindowProc(IntPtr hwnd, uint umsg, IntPtr wParam, IntPtr lParam)
{
var msg = (WM)umsg;
switch (msg)
{
case WM.KEYDOWN:
{
switch (wParam.ToInt32())
{
// 27 - flag for esc
case 27:
{
User32Methods.PostQuitMessage(0);
break;
}
}
break;
}
case WM.LBUTTONDOWN:
{
mousePressed = true;
User32Methods.GetCursorPos(out lastMousePos);
User32Methods.GetCursorPos(out currentMousePos);
break;
}
case WM.MOUSEMOVE:
{
if (mousePressed)
User32Methods.GetCursorPos(out currentMousePos);
break;
}
case WM.LBUTTONUP:
{
mousePressed = false;
break;
}
case WM.CLOSE:
{
User32Methods.PostQuitMessage(0);
break;
}
case WM.PAINT:
{
IntPtr bm = new IntPtr();
PaintStruct ps;
var hdc = User32Methods.BeginPaint(hwnd, out ps);
IntPtr hdcMem = Gdi32Methods.CreateCompatibleDC(hdc);
IntPtr hbmOld = Gdi32Methods.SelectObject(hdcMem, bmp);
Gdi32Methods.GetObject(bmp, 0, bm);
Gdi32Methods.BitBlt(hdc, virtualScreenLeft, virtualScreenTop,
virtualScreenWidth, virtualScreenHeight,
hdcMem, 0, 0, BitBltFlags.SRCCOPY);
Gdi32Methods.SelectObject(hdcMem, hbmOld);
Gdi32Methods.DeleteDC(hdcMem);
rect.Left = lastMousePos.X;
rect.Top = lastMousePos.Y;
rect.Right = currentMousePos.X;
rect.Bottom = lastMousePos.Y;
User32Methods.FillRect(hdc, ref rect,
Gdi32Helpers.GetStockObject(StockObject.WHITE_BRUSH));
User32Methods.EndPaint(hwnd, ref ps);
break;
}
}
return User32Methods.DefWindowProc(hwnd, umsg, wParam, lParam);
}
}
【问题讨论】:
-
“即使我正在更新窗口”,sn-p 也没有显示任何证据。使用 InvalidateRect() 强制重绘。