找回密码
 加入
搜索
查看: 7720|回复: 14

[GUI管理] 父子窗口的消息传递问题[已解决]

[复制链接]
发表于 2013-7-14 13:54:27 | 显示全部楼层 |阅读模式
本帖最后由 seniors 于 2013-7-15 18:45 编辑

我父窗口和子窗口(控件)全部是完全自绘
现在是子窗口的点击消息能发送给父窗口,但是只能在父窗口的窗口处理函数中看到,而且点击了一次会收到10多个消息
我不知道是不是我的鼠标有问题,请高人指教一下
原来C++中这样的代码可以用
同时收到多个消息的原因是postmessage的条件不对

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
发表于 2013-7-14 18:07:45 | 显示全部楼层
本帖最后由 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[0];
EndFunc   ;==>GetMessage
Func TranslateMessage($lpMSG)
        Local $Ret = DllCall($hDLL, "bool", "TranslateMessage", "ptr", $lpMSG)
        Return $Ret[0]
EndFunc   ;==>TranslateMessage
Func DispatchMessage($lpMSG)
        Local $Ret = DllCall($hDLL, "lresult", "DispatchMessageW", "ptr", $lpMSG)
        Return $Ret[0] 
EndFunc   ;==>DispatchMessage
 楼主| 发表于 2013-7-15 05:32:42 | 显示全部楼层
回复 2# Ycxw2008

我不想放在回调函数中处理,谢谢Ycxw2008
发表于 2013-7-15 12:56:49 | 显示全部楼层
回复 3# seniors

好像你要自定义控件类的话 可能不太好搞吧?
MFC好像也是SetWindowLong 子类化的
发表于 2013-7-15 15:20:57 | 显示全部楼层
本帖最后由 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[0];
EndFunc   ;==>GetMessage

Func TranslateMessage($lpMSG)
        Local $Ret = DllCall($hDLL, "bool", "TranslateMessage", "ptr", $lpMSG)
        Return $Ret[0]
EndFunc   ;==>TranslateMessage

Func DispatchMessage($lpMSG)
        Local $Ret = DllCall($hDLL, "lresult", "DispatchMessageW", "ptr", $lpMSG)
        Return $Ret[0] ;If Not @error Then Return $Ret[0];
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);
}
 楼主| 发表于 2013-7-15 18:42:11 | 显示全部楼层
噢,原来同样的代码C++就行,谢谢了
另:看到好多建议不要while(GetMessage( &msg, hWnd, 0, 0 )== 1)
发表于 2013-7-15 22:18:39 | 显示全部楼层
回复 6# seniors

额,知道那句在c++不好
不过在au3里 只有这样才有用

        If _GetMessage($pMsg, 0, 0, 0) < 1 Then

                ExitLoop

        EndIf

你试试在ExitLoop上面加句MsgBox看看,断的到吗?
 楼主| 发表于 2013-7-16 18:58:23 | 显示全部楼层
回复 7# Ycxw2008

没想到在上面放一句msgbox会不起作用,是为什么呢?
发表于 2013-7-17 22:28:34 | 显示全部楼层
回复 8# seniors


    这个问题可能要请教P大了。。
    其实我也不太懂。
    也不知为什么PeekMessage的返回值 都是0
发表于 2013-7-18 08:46:20 | 显示全部楼层
这个 要标记下 ··QQ原理··
发表于 2013-7-18 08:46:25 | 显示全部楼层
这个 要标记下 ··QQ原理··
 楼主| 发表于 2013-7-19 09:54:36 | 显示全部楼层
回复 9# Ycxw2008
我不想纠结于这个问题了,我觉得可能是两个回调函数后,系统有点紊乱,下次有空做一个全部在一个回调函数里的,带控件的代码,AU3编界面太累。
发表于 2013-7-19 14:42:19 | 显示全部楼层
本帖最后由 Ycxw2008 于 2013-7-19 14:44 编辑

回复 12# seniors

     是有点累,特别是自绘 哈哈
     就处理Rect 老要DllStruct处理就觉得不太方便 :(

    我用OD 对比了下 au3和c++  
    au3 默认会创建窗口,所以本来的消息循环肯定被处理了
发表于 2013-7-20 16:43:27 | 显示全部楼层
学习了,受教受教....
发表于 2017-3-8 18:09:31 | 显示全部楼层
好高深,看不懂.....
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-3-28 20:17 , Processed in 0.087894 second(s), 24 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表