rob*_*rtv 2 c winapi visual-studio
我有一些示例代码,它只是在 Windows 10 中的屏幕上放置一个窗口。该程序在 32 位下运行良好:窗口回调过程在窗口创建时发送消息。
在 32 位下,前三个消息是:
WM_GETMINMAXINFO
WM_NCCREATE
WM_NCCALCSIZE
Run Code Online (Sandbox Code Playgroud)
然后从那里开始直到构建窗口。
但是,在 64 位下,这不会发生;相反,这些是发送的消息:
WM_GETMINMAXINFO
WM_NCCREATE
WM_NCDESTROY
Run Code Online (Sandbox Code Playgroud)
如您所见,在创建窗口后,操作系统立即发送一条消息来销毁它!
这是实际的代码:
/*****************************************************************************/
/* This sample demonstrates how to continuously acquire pictures */
#include <windows.h>
#include <stdio.h>
#define _NIWIN
#define PB_QUIT 101 /* id for quit application push button */
// Window proc
LRESULT CALLBACK ImaqSmplProc(HWND hWnd, UINT iMessage, UINT wParam, LONG lParam);
// windows GUI globals
static HINSTANCE hInst;
static HWND ImaqSmplHwnd;
static HWND HStop, HGrab, HQuit, HIntfName, HFrameRate;
static long CanvasWidth = 512; // width of the display area
static long CanvasHeight = 384; // height of the display area
static long CanvasTop = 10; // top of the display area
static long CanvasLeft = 10; // left of the display area
static long AcqWinWidth;
static long AcqWinHeight;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
CHAR ImaqSmplClassName[] = "Imaq Sample";
WNDCLASS ImaqSmplClass;
MSG msg;
// register the main window
hInst = hInstance;
if (!hPrevInstance)
{
ImaqSmplClass.style = CS_HREDRAW | CS_VREDRAW;
ImaqSmplClass.lpfnWndProc = (WNDPROC) ImaqSmplProc;
ImaqSmplClass.cbClsExtra = 0;
ImaqSmplClass.cbWndExtra = 0;
ImaqSmplClass.hInstance = hInstance;
ImaqSmplClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
ImaqSmplClass.hCursor = LoadCursor (NULL, IDC_ARROW);
ImaqSmplClass.hbrBackground = GetStockObject(LTGRAY_BRUSH);
ImaqSmplClass.lpszMenuName = 0;
ImaqSmplClass.lpszClassName = ImaqSmplClassName;
if (!RegisterClass (&ImaqSmplClass))
return (0);
}
// creates the main window
ImaqSmplHwnd = CreateWindow(ImaqSmplClassName, "LLGrab", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, 680, 440, NULL, NULL, hInstance, NULL);
// creates the quit application button
if (!(HQuit = CreateWindow("Button","Quit",BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE,
550,152,80,40,ImaqSmplHwnd,(HMENU)PB_QUIT,hInstance,NULL)))
return(FALSE);
// Display the main window
ShowWindow(ImaqSmplHwnd, SW_SHOW);
UpdateWindow(ImaqSmplHwnd);
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return (int)(msg.wParam);
}
// Message proc
LRESULT CALLBACK ImaqSmplProc(HWND hWnd, UINT iMessage, UINT wParam, LONG lParam)
{
WORD wmId;
LRESULT theResult;
switch (iMessage)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
switch (wmId)
{
case PB_QUIT:
PostQuitMessage(0);
break;
}
break;
case WM_NCDESTROY:
break;
case WM_DESTROY:
PostQuitMessage(0);
default:
theResult = DefWindowProc(hWnd, iMessage, wParam, lParam);
return theResult;
break;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
您的ImaqSmplProc()窗口过程声明不正确,导致您将错误数据传递给DefWindowProc().
对于WM_NCCREATE,lParam持有一个指针,您在 64 位以下将其截断为 32 位值,因此DefWindowProc()无法WM_NCCREATE正确处理,从而导致CreateWindow()破坏窗口。如果您调试代码,您可能会在处理错误值时看到DefWindowProc()返回。FALSEWM_NCCREATElParam
如果应用程序处理此消息,它应返回 TRUE 以继续创建窗口。如果应用程序返回 FALSE,则 CreateWindow 或 CreateWindowEx 函数将返回一个 NULL 句柄。
为了解决这个问题,wParam和lParam参数必须分别声明为WPARAM和LPARAM:
LRESULT CALLBACK ImaqSmplProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
Run Code Online (Sandbox Code Playgroud)
这与 的实际签名匹配WNDPROC:
LRESULT CALLBACK WindowProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
Run Code Online (Sandbox Code Playgroud)
WPARAM和LPARAM分别声明为UINT_PTR和LONG_PTR。这意味着它们是指针大小的整数,因此在 32 位和 64 位下具有不同的大小。而UINT和LONG在 32 位和 64 位上具有相同的大小。请参阅Windows 数据类型。您的原始代码没有考虑到这种差异。
您使用了类型转换来使编译器不向您发出错误声明的警告。分配ImaqSmplProc给时,您需要摆脱类型转换ImaqSmplClass.lpfnWndProc:
ImaqSmplClass.lpfnWndProc = ImaqSmplProc;
Run Code Online (Sandbox Code Playgroud)
任何时候你发现自己在使用类型转换,问问自己为什么,你可能做错了什么。除非绝对需要,否则不要使用类型转换。不要仅仅为了让编译器保持沉默而使用类型转换,它会出于某种原因抱怨有问题/错误的事情。
| 归档时间: |
|
| 查看次数: |
99 次 |
| 最近记录: |