更改 window 的 WndProc
Change WndProc of the window
我尝试更改标准 WndProc
函数。我有这个代码:
HWND btn = CreateWindowEx(WS_EX_TRANSPARENT | WS_EX_CLIENTEDGE, L"BUTTON", L"Window title", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON
, 50, 50, 50, 50, (HWND)XApplicationMainWindow->window->_wnd, (HMENU)123,
(HINSTANCE)GetWindowLongPtr(XApplicationMainWindow->window->_wnd, GWLP_HINSTANCE), NULL);
SetWindowLongPtrW(btn, GWLP_WNDPROC, (LONG_PTR)SubclassWindowProc);
我可以使用 L"BUTTON"
class 名称,但是当我更改 WndProc
功能时我会遇到问题。
在这张图片上,你可以看到空白的方块和普通的按钮。如果我尝试创建新的 WNDCLASS or WNDCLASSEX
,我将一无所有...为什么?
如果我使用 L"BUTTON"
class 名称,如何更改标准 WndProc
函数?
这是我的第二个WndProc
:
LRESULT CALLBACK SubclassWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CREATE:
break;
case WM_COMMAND:
//Event click
switch (LOWORD(wParam))
{
case 123:
OutputDebugStringA("Subclass click2");
break;
default:
break;
}
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
DefWindowProc()
是您 SubclassWindowProc()
调用的错误 window 程序。
您需要调用要替换的 previous window 过程 - window 过程处理按钮的所有默认行为(如绘图按钮,所以它实际上看起来像一个按钮,并像按钮一样响应用户输入,等等)。 SetWindowLongPtr()
returns 向您提供指向该过程的指针,但您目前正在忽略它。
有关详细信息,请参阅 MSDN 上的 Subclassing Controls。
试试这个:
WNDPROC btnWndProc;
LRESULT CALLBACK SubclassWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_COMMAND:
//Event click
switch (LOWORD(wParam))
{
case 123:
OutputDebugStringA("Subclass click2");
break;
}
break;
}
return CallWindowProc(hWnd, btnWndProc, uMsg, wParam, lParam);
}
...
HWND btn = CreateWindowEx(...);
btnWndProc = (WNDPROC) SetWindowLongPtrW(btn, GWLP_WNDPROC, (LONG_PTR)SubclassWindowProc);
或者,使用SetWindowSubclass()
, which is safer than using SetWindowsLongPtr()
,例如:
LRESULT CALLBACK SubclassWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
switch (uMsg) {
case WM_NCDESTROY:
RemoveWindowSubclass(hWnd, SubclassWindowProc, uIdSubclass);
break;
case WM_COMMAND:
//Event click
switch (LOWORD(wParam))
{
case 123:
OutputDebugStringA("Subclass click2");
break;
}
break;
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
...
HWND btn = CreateWindowEx(...);
SetWindowSubclass(btn, SubclassWindowProc, 1, 0);
话虽如此,您的子类永远不会调用 OutputDebugStringA()
,因为它永远不会收到您期望的 WM_COMMAND
消息。单击按钮时,不会向按钮本身发送 WM_COMMAND
消息。该按钮将 WM_COMMAND
消息发送到按钮的 父级 window(在本例中为 XApplicationMainWindow->window->_wnd
)。因此,您需要在 parent window 的 window 过程中处理 WM_COMMAND
消息,而不是在 window 的 window 过程中按钮本身。
否则,如果您仍想子类化按钮本身,则必须处理按钮接收到的 WM_LBUTTON(DOWN|UP)
和 WM_KEY(DOWN|UP)
/WM_CHAR
消息,然后将其转换为一个 WM_COMMAND
消息给它的父 window.
我尝试更改标准 WndProc
函数。我有这个代码:
HWND btn = CreateWindowEx(WS_EX_TRANSPARENT | WS_EX_CLIENTEDGE, L"BUTTON", L"Window title", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON
, 50, 50, 50, 50, (HWND)XApplicationMainWindow->window->_wnd, (HMENU)123,
(HINSTANCE)GetWindowLongPtr(XApplicationMainWindow->window->_wnd, GWLP_HINSTANCE), NULL);
SetWindowLongPtrW(btn, GWLP_WNDPROC, (LONG_PTR)SubclassWindowProc);
我可以使用 L"BUTTON"
class 名称,但是当我更改 WndProc
功能时我会遇到问题。
在这张图片上,你可以看到空白的方块和普通的按钮。如果我尝试创建新的 WNDCLASS or WNDCLASSEX
,我将一无所有...为什么?
如果我使用 L"BUTTON"
class 名称,如何更改标准 WndProc
函数?
这是我的第二个WndProc
:
LRESULT CALLBACK SubclassWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CREATE:
break;
case WM_COMMAND:
//Event click
switch (LOWORD(wParam))
{
case 123:
OutputDebugStringA("Subclass click2");
break;
default:
break;
}
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
DefWindowProc()
是您 SubclassWindowProc()
调用的错误 window 程序。
您需要调用要替换的 previous window 过程 - window 过程处理按钮的所有默认行为(如绘图按钮,所以它实际上看起来像一个按钮,并像按钮一样响应用户输入,等等)。 SetWindowLongPtr()
returns 向您提供指向该过程的指针,但您目前正在忽略它。
有关详细信息,请参阅 MSDN 上的 Subclassing Controls。
试试这个:
WNDPROC btnWndProc;
LRESULT CALLBACK SubclassWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_COMMAND:
//Event click
switch (LOWORD(wParam))
{
case 123:
OutputDebugStringA("Subclass click2");
break;
}
break;
}
return CallWindowProc(hWnd, btnWndProc, uMsg, wParam, lParam);
}
...
HWND btn = CreateWindowEx(...);
btnWndProc = (WNDPROC) SetWindowLongPtrW(btn, GWLP_WNDPROC, (LONG_PTR)SubclassWindowProc);
或者,使用SetWindowSubclass()
, which is safer than using SetWindowsLongPtr()
,例如:
LRESULT CALLBACK SubclassWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
switch (uMsg) {
case WM_NCDESTROY:
RemoveWindowSubclass(hWnd, SubclassWindowProc, uIdSubclass);
break;
case WM_COMMAND:
//Event click
switch (LOWORD(wParam))
{
case 123:
OutputDebugStringA("Subclass click2");
break;
}
break;
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
...
HWND btn = CreateWindowEx(...);
SetWindowSubclass(btn, SubclassWindowProc, 1, 0);
话虽如此,您的子类永远不会调用 OutputDebugStringA()
,因为它永远不会收到您期望的 WM_COMMAND
消息。单击按钮时,不会向按钮本身发送 WM_COMMAND
消息。该按钮将 WM_COMMAND
消息发送到按钮的 父级 window(在本例中为 XApplicationMainWindow->window->_wnd
)。因此,您需要在 parent window 的 window 过程中处理 WM_COMMAND
消息,而不是在 window 的 window 过程中按钮本身。
否则,如果您仍想子类化按钮本身,则必须处理按钮接收到的 WM_LBUTTON(DOWN|UP)
和 WM_KEY(DOWN|UP)
/WM_CHAR
消息,然后将其转换为一个 WM_COMMAND
消息给它的父 window.