父子窗口的消息传递问题[已解决]
本帖最后由 seniors 于 2013-7-15 18:45 编辑我父窗口和子窗口(控件)全部是完全自绘
现在是子窗口的点击消息能发送给父窗口,但是只能在父窗口的窗口处理函数中看到,而且点击了一次会收到10多个消息
我不知道是不是我的鼠标有问题,请高人指教一下
原来C++中这样的代码可以用
同时收到多个消息的原因是postmessage的条件不对
本帖最后由 Ycxw2008 于 2013-7-14 21:44 编辑
回复 1# seniors
这样试试呢??不过我感觉还是不太对,好像要处理WM_NOTIFY?
;~ #include <DirUIGui.au3>
#include "DirUIbutton.au3"
#include <APIConstants.au3>
#include <WinAPIEx.au3>
Global Const $szWindowClass = "MyTestClass", $szTitle = "MyTestWindow"
Global Const $tagMSG = "hwnd hwnd; uint message; wparam wParam; lparam lParam; dword time; long X;long Y"
Global $hDLL, $nWidth, $nHeight
Global $wProcNew = DllCallbackRegister("BtnProc", "ptr", "hwnd;uint;long;ptr")
Global $wProcOld,$nButton
WinMain(_WinAPI_GetModuleHandle(0), 0, $WS_OVERLAPPEDWINDOW)
Func WindowProc($hWnd, $iMsg, $wParam, $lParam)
Switch $iMsg
Case $WM_CREATE
$nCtrlID = __UDF_GetNextGlobalID($hWnd)
Local $Button = _WinAPI_CreateWindowEx(0, "Button", "test", BitOR($WS_CHILD, $WS_VISIBLE, 0x00000001), 10, 10, 100, 50, $hWnd, $nCtrlID)
$nButton=$nCtrlID
$wProcOld = _WinAPI_SetWindowLong($Button, $GWL_WNDPROC, DllCallbackGetPtr($wProcNew))
Case $WM_COMMAND
If _WinAPI_LoWord($wParam) == $nButton Then
MsgBox(0,"","是我")
EndIf
Case $WM_CHAR
If $wParam == $VK_ESCAPE Then Return _WinAPI_DestroyWindow($hWnd)
Case $WM_DESTROY
DllCall($hDLL, "void", "PostQuitMessage", "int", 0)
Case Else
Return _WinAPI_DefWindowProcW($hWnd, $iMsg, $wParam, $lParam)
EndSwitch
Return 0
EndFunc ;==>WindowProc
Func BtnProc($hWnd, $iMsg, $wParam, $lParam)
Switch $iMsg
Case $WM_PAINT
Local $ps,$hDC=_WinAPI_BeginPaint($hWnd,$ps)
$rc=_WinAPI_GetClientRect($hWnd)
$hMemDC=_WinAPI_CreateCompatibleDC($hDC)
$hBitmap=_WinAPI_CreateCompatibleBitmapEx($hDC,DllStructGetData($rc,3),DllStructGetData($rc,4),0xFFFFFF)
$hOld=_WinAPI_SelectObject($hMemDC,$hBitmap)
_WinAPI_DrawText($hMemDC,"点我",$rc,BitOR($DT_SINGLELINE,$DT_CENTER,$DT_VCENTER))
_WinAPI_BitBlt($hDC,0,0,DllStructGetData($rc,3),DllStructGetData($rc,4),$hMemDC,0,0,$SRCCOPY)
_WinAPI_SelectObject($hMemDC,$hOld)
_WinAPI_DeleteDC($hMemDC)
Return _WinAPI_EndPaint($hWnd,$ps)
EndSwitch
Return _WinAPI_CallWindowProc($wProcOld, $hWnd, $iMsg, $wParam, $lParam)
EndFunc ;==>BtnProc
Func WinMain($hInstance, $dwExStyle, $dwStyle)
Local $MSG = DllStructCreate($tagMSG)
Local $pMSG = DllStructGetPtr($MSG)
Local $hProc = DllCallbackRegister('WindowProc', 'lresult', 'hwnd;uint;wparam;lparam')
MyRegisterClass($hInstance, DllCallbackGetPtr($hProc))
Local $hWnd = _WinAPI_CreateWindowEx( _
$dwExStyle, _
$szWindowClass, _
$szTitle, _
$dwStyle, _
(@DesktopWidth - 400) / 2, _
(@DesktopHeight - 300) / 2, _
400, _
300, _
0)
If Not $hWnd Then Return 0
_WinAPI_ShowWindow($hWnd)
;~ _WinAPI_UpdateWindow($hWnd)
$hDLL = DllOpen("User32.dll")
While GetMessage($pMSG, $hWnd) == 1
TranslateMessage($pMSG)
DispatchMessage($pMSG)
WEnd
ConsoleWrite("Exit" & @CRLF)
DllClose($hDLL)
_WinAPI_UnregisterClass($szWindowClass, $hInstance)
DllCallbackFree($hProc)
EndFunc ;==>WinMain
Func MyRegisterClass($hInstance, $WindowProc)
Local $wcex = DllStructCreate($tagWNDCLASSEX)
DllStructSetData($wcex, 'Size', DllStructGetSize($wcex))
DllStructSetData($wcex, 'Style', 0)
DllStructSetData($wcex, 'hWndProc', $WindowProc)
DllStructSetData($wcex, 'ClsExtra', 0)
DllStructSetData($wcex, 'WndExtra', 0)
DllStructSetData($wcex, 'hInstance', $hInstance)
DllStructSetData($wcex, 'hIcon', 0)
DllStructSetData($wcex, 'hCursor', _WinAPI_LoadCursor(0, 32512))
DllStructSetData($wcex, 'hBackground', _WinAPI_GetStockObject($NULL_BRUSH))
DllStructSetData($wcex, 'MenuName', 0)
DllStructSetData($wcex, 'ClassName', _WinAPI_CreateString($szWindowClass))
DllStructSetData($wcex, 'hIconSm', 0)
Return _WinAPI_RegisterClassEx($wcex)
EndFunc ;==>MyRegisterClass
Func GetMessage($lpMSG, $hWnd)
Local $Ret = DllCall($hDLL, "bool", "GetMessageW", "ptr", $lpMSG, "handle", $hWnd, "uint", 0, "uint", 0);
Return $Ret;
EndFunc ;==>GetMessage
Func TranslateMessage($lpMSG)
Local $Ret = DllCall($hDLL, "bool", "TranslateMessage", "ptr", $lpMSG)
Return $Ret
EndFunc ;==>TranslateMessage
Func DispatchMessage($lpMSG)
Local $Ret = DllCall($hDLL, "lresult", "DispatchMessageW", "ptr", $lpMSG)
Return $Ret
EndFunc ;==>DispatchMessage
回复 2# Ycxw2008
我不想放在回调函数中处理,谢谢Ycxw2008 回复 3# seniors
好像你要自定义控件类的话 可能不太好搞吧?
MFC好像也是SetWindowLong 子类化的 本帖最后由 Ycxw2008 于 2013-7-15 16:12 编辑
回复 3# seniors
或许是au3方面的问题 同样的代码
在c++里 就可以很正常
2段代码在下面
au3;~ #include "DirUIbutton.au3"
#include <APIConstants.au3>
#include <WinAPIEx.au3>
Global Const $szWindowClass = "MyTestClass", $szTitle = "MyTestWindow"
Global Const $tagMSG = "hwnd hwnd; uint message; wparam wParam; lparam lParam; dword time; long X;long Y"
Global $hDLL, $nWidth, $nHeight
WinMain(_WinAPI_GetModuleHandle(0), 0, $WS_OVERLAPPEDWINDOW)
Func WindowProc($hWnd, $iMsg, $wParam, $lParam)
Switch $iMsg
Case $WM_COMMAND
MsgBox(0, "", "回调里能收到")
Return 0
Case $WM_CHAR
If $wParam == $VK_ESCAPE Then Return _WinAPI_DestroyWindow($hWnd)
Return 0
Case $WM_DESTROY
DllCall($hDLL, "void", "PostQuitMessage", "int", 0)
Return 0
EndSwitch
Return _WinAPI_DefWindowProcW($hWnd, $iMsg, $wParam, $lParam)
EndFunc ;==>WindowProc
Func _BtnProc($hWnd, $iMsg, $wParam, $lParam)
Switch $iMsg
Case $WM_LBUTTONDOWN;左键点击
_WinAPI_PostMessage(_WinAPI_GetParent($hWnd), $WM_COMMAND, _WinAPI_MakeLong(_WinAPI_GetDlgCtrlID($hWnd), 0), $lParam)
Return 0
Case $WM_PAINT;处理绘制信息
Local $ps
Local $hDC = _WinAPI_BeginPaint($hWnd, $ps)
$rc = _WinAPI_GetClientRect($hWnd)
_WinAPI_Rectangle($hDC, $rc)
_WinAPI_EndPaint($hWnd, $ps)
Return 0
EndSwitch
Return _WinAPI_DefWindowProcW($hWnd, $iMsg, $wParam, $lParam)
EndFunc ;==>_BtnProc
Func WinMain($hInstance, $dwExStyle, $dwStyle)
Local $MSG = DllStructCreate($tagMSG)
Local $pMSG = DllStructGetPtr($MSG)
Local $hProc = DllCallbackRegister('WindowProc', 'lresult', 'hwnd;uint;wparam;lparam')
Local $wcex = DllStructCreate($tagWNDCLASSEX)
DllStructSetData($wcex, 'Size', DllStructGetSize($wcex))
DllStructSetData($wcex, 'Style', 0)
DllStructSetData($wcex, 'hWndProc', DllCallbackGetPtr($hProc))
DllStructSetData($wcex, 'ClsExtra', 0)
DllStructSetData($wcex, 'WndExtra', 0)
DllStructSetData($wcex, 'hInstance', $hInstance)
DllStructSetData($wcex, 'hIcon', 0)
DllStructSetData($wcex, 'hCursor', _WinAPI_LoadCursor(0, 32512))
DllStructSetData($wcex, 'hBackground', _WinAPI_GetStockObject($NULL_BRUSH))
DllStructSetData($wcex, 'MenuName', 0)
DllStructSetData($wcex, 'ClassName', _WinAPI_CreateString($szWindowClass))
DllStructSetData($wcex, 'hIconSm', 0)
_WinAPI_RegisterClassEx($wcex)
$__DirUIButoon_hProc = DllCallbackRegister('_BtnProc', 'lresult', 'hwnd;uint;wparam;lparam')
DllStructSetData($wcex, 'hWndProc', DllCallbackGetPtr($__DirUIButoon_hProc))
DllStructSetData($wcex, 'ClassName', _WinAPI_CreateString("test"))
_WinAPI_RegisterClassEx($wcex)
Local $hWnd = _WinAPI_CreateWindowEx( _
$dwExStyle, _
$szWindowClass, _
$szTitle, _
$dwStyle, _
(@DesktopWidth - 400) / 2, _
(@DesktopHeight - 300) / 2, _
400, _
300, _
0, _
0, _
$hInstance, _
0)
If Not $hWnd Then Return 0
_WinAPI_ShowWindow($hWnd)
_WinAPI_UpdateWindow($hWnd)
$hDLL = DllOpen("User32.dll")
_WinAPI_CreateWindowEx(0, "test", "", BitOR($WS_CHILD, $WS_VISIBLE, $WS_TABSTOP, 0x4000), 0, 0, 50, 50, $hWnd, 0, 0, 0)
;~ _DirUIButoon_Create($hWnd, "test", 0, 0, 50, 50)
While GetMessage($MSG, $hWnd) == 1
If DllStructGetData($pMSG, "message") == $WM_COMMAND Then
MsgBox(0, '', '')
EndIf
TranslateMessage($pMSG)
DispatchMessage($pMSG)
WEnd
DllClose($hDLL)
_WinAPI_UnregisterClass($szWindowClass, $hInstance)
DllCallbackFree($hProc)
EndFunc ;==>WinMain
Func GetMessage($lpMSG, $hWnd)
Local $Ret = DllCall($hDLL, "bool", "GetMessageW", "ptr", $lpMSG, "handle", $hWnd, "uint", 0, "uint", 0);
Return $Ret;
EndFunc ;==>GetMessage
Func TranslateMessage($lpMSG)
Local $Ret = DllCall($hDLL, "bool", "TranslateMessage", "ptr", $lpMSG)
Return $Ret
EndFunc ;==>TranslateMessage
Func DispatchMessage($lpMSG)
Local $Ret = DllCall($hDLL, "lresult", "DispatchMessageW", "ptr", $lpMSG)
Return $Ret ;If Not @error Then Return $Ret;
EndFunc ;==>DispatchMessage
C++#include <stdio.h>
#include <Windows.h>
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
LRESULT CALLBACK BtnProc(HWND,UINT,WPARAM,LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
{
AllocConsole();
FILE *stream;
freopen_s(&stream,"CONIN$","r",stdin);
freopen_s(&stream,"CONOUT$","w",stdout);
printf("%s\n","test");
WNDCLASSEXW wcex;
wcex.cbSize=sizeof(WNDCLASSEX);
wcex.style = 0;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = 0;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = 0;
wcex.lpszMenuName = 0;
wcex.lpszClassName=L"test";
wcex.hIconSm=0;
RegisterClassExW(&wcex);
wcex.lpszClassName=L"TestButton";
wcex.lpfnWndProc=BtnProc;
RegisterClassExW(&wcex);
HWND hWnd=CreateWindowExW(0,L"test",L"test",WS_OVERLAPPEDWINDOW,0,0, 400, 300,0,0,hInstance,0);
if(!hWnd)
return 0;
ShowWindow(hWnd,nCmdShow);
UpdateWindow(hWnd);
MSG msg;
CreateWindowExW(0,L"TestButton",L"",WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_NOTIFY,0,0,50,50,hWnd,0,0,0);
while(GetMessage( &msg, hWnd, 0, 0 )== 1)
{
if (msg.message==WM_COMMAND)
{
MessageBoxA(0,"循环里也能收到","",0);
printf("%s\n","循环里也能收到");
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
FreeConsole();
return 0;
}
LRESULT CALLBACK BtnProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_LBUTTONDOWN:
PostMessage(GetParent(hwnd),WM_COMMAND,MAKELONG(GetDlgCtrlID(hwnd),BN_CLICKED),(LPARAM)hwnd);
return 0;
case WM_PAINT:
{
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rect) ;
Rectangle (hdc, 0, 0, rect.right, rect.bottom) ;
EndPaint (hwnd, &ps) ;
}
return 0;
}
return DefWindowProcW(hwnd,message,wParam,lParam);
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
MessageBoxA(0,"回调里也能收到","",0);
printf("%s\n","回调里也能收到");
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProcW(hwnd,message,wParam,lParam);
} 噢,原来同样的代码C++就行,谢谢了
另:看到好多建议不要while(GetMessage( &msg, hWnd, 0, 0 )== 1) 回复 6# seniors
额,知道那句在c++不好
不过在au3里 只有这样才有用
If _GetMessage($pMsg, 0, 0, 0) < 1 Then
ExitLoop
EndIf
你试试在ExitLoop上面加句MsgBox看看,断的到吗? 回复 7# Ycxw2008
没想到在上面放一句msgbox会不起作用,是为什么呢? 回复 8# seniors
这个问题可能要请教P大了。。
其实我也不太懂。
也不知为什么PeekMessage的返回值 都是0{:face (394):} 这个 要标记下 ··QQ原理·· 这个 要标记下 ··QQ原理·· 回复 9# Ycxw2008
我不想纠结于这个问题了,我觉得可能是两个回调函数后,系统有点紊乱,下次有空做一个全部在一个回调函数里的,带控件的代码,AU3编界面太累。 本帖最后由 Ycxw2008 于 2013-7-19 14:44 编辑
回复 12# seniors
是有点累,特别是自绘 哈哈
就处理Rect 老要DllStruct处理就觉得不太方便 :(
我用OD 对比了下 au3和c++
au3 默认会创建窗口,所以本来的消息循环肯定被处理了 学习了,受教受教.... 好高深,看不懂.....
{:face (319):}
页:
[1]