Вложенные вызовы из WndProc по умолчанию - PullRequest
3 голосов
/ 16 октября 2011

У меня есть следующий вывод из Spy ++:

<00227> 001F1732 P WM_MOUSEMOVE fwKeys:MK_LBUTTON xPos:-43 yPos:28
<00228> 001F1732 S WM_SIZING fwSide:WMSZ_LEFT lprc:0012F410
<00229> 001F1732 R WM_SIZING fProcessed:False
<00230> 001F1732 S WM_WINDOWPOSCHANGING lpwp:0012F404
<00231> 001F1732 S  WM_GETMINMAXINFO lpmmi:0012EEF4
<00232> 001F1732 R  WM_GETMINMAXINFO lpmmi:0012EEF4
<00233> 001F1732 R WM_WINDOWPOSCHANGING
<00234> 001F1732 S WM_NCCALCSIZE fCalcValidRects:True lpncsp:0012F3D8
<00235> 001F1732 R WM_NCCALCSIZE fuValidRect:0000 lpncsp:0012F3D8
<00236> 001F1732 S WM_NCPAINT hrgn:00000001
<00237> 001F1732 R WM_NCPAINT
<00238> 001F1732 S WM_ERASEBKGND hdc:09012308
<00239> 001F1732 R WM_ERASEBKGND fErased:True
<00240> 001F1732 S WM_WINDOWPOSCHANGED lpwp:0012F404
<00241> 001F1732 S  WM_MOVE xPos:950 yPos:404
<00242> 001F1732 R  WM_MOVE
<00243> 001F1732 S  WM_SIZE fwSizeType:SIZE_RESTORED nWidth:282 nHeight:79
<00244> 001F1732 R  WM_SIZE
<00245> 001F1732 S  WM_WINDOWPOSCHANGING lpwp:0012F064
<00246> 001F1732 R  WM_WINDOWPOSCHANGING
<00247> 001F1732 S  WM_NCCALCSIZE fCalcValidRects:True lpncsp:0012F038
<00248> 001F1732 R  WM_NCCALCSIZE fuValidRect:0000 lpncsp:0012F038
<00249> 001F1732 S  WM_NCPAINT hrgn:00000001
<00250> 001F1732 R  WM_NCPAINT
<00251> 001F1732 S  WM_ERASEBKGND hdc:16011DB5
<00252> 001F1732 R  WM_ERASEBKGND fErased:True
<00253> 001F1732 S  WM_WINDOWPOSCHANGED lpwp:0012F064
<00254> 001F1732 R  WM_WINDOWPOSCHANGED
<00255> 001F1732 R WM_WINDOWPOSCHANGED
<00256> 001F1732 S WM_PAINT hdc:00000000
<00257> 001F1732 R WM_PAINT
<00258> 001F1732 P WM_MOUSEMOVE fwKeys:MK_LBUTTON xPos:-9 yPos:28

Отступы в строках с 241 по 254 были добавлены мной, чтобы сделать более очевидным, что эти сообщения являются вложенными. То есть они были отправлены с помощью сообщения WM_WINDOWPOSCHANGED в строке 240.

Вот связанный WndProc (это все из проекта по умолчанию, созданного Visual Studio 2005, за исключением случаев, когда он помечен для отображения кода, который я добавил):

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;
    LRESULT lReturnValue = 0; //---added by me
    static int lcount = 0; //---added by me

    switch (message)
    {
    //---added by me from here vvvv
    case WM_WINDOWPOSCHANGED:
        ++lcount;
        lReturnValue = DefWindowProc(hWnd, message, wParam, lParam);
        //--lcount;
        return lReturnValue;
    case WM_ERASEBKGND:
    case WM_NCPAINT:
        {
            wchar_t a[20];
            _itow(lcount, &a[0], 10);
            OutputDebugString(a);
            OutputDebugString(L"\n");
        }
        return DefWindowProc(hWnd, message, wParam, lParam);
    //---added by me to here ^^^^
    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // Parse the menu selections:
        switch (wmId)
        {
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        // TODO: Add any drawing code here...
        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

Если я запускаю это, в окне вывода VS есть следующее:

0
0
1
1
1
1
2
2
2
2
etc

Если я раскомментирую

//--lcount;

строка, которую я получаю:

0
0
0
0
0
0
0
0
etc

Я не понимаю, почему? Я ожидаю получить:

0
0
1
1
0
0
1
1
etc

, где 1 представляют вызовы WM_ERASEBKGND и WM_NCPAINT изнутри WM_WINDOWPOSCHANGED (как показано в выходных данных Spy ++). Очевидно, с моей стороны есть какое-то фундаментальное недоразумение, и я не могу этого понять! Любые идеи / предложения, чтобы попытаться с благодарностью приняты ...

Если вы согласны с тем, что я назвал своим ожидаемым поведением для этого кода, я также был бы признателен за комментарий. Таким образом, я знаю, что не смотрю на это совершенно неправильно. :)

Редактировать: Я думаю, что Spy ++ лжет! Я добавил вызов OutputDebugString в верхней части WndProc, чтобы вывести число каждые сообщения, полученные окном и получившие:

[WM_MOUSEMOVE] // not received
WM_SIZING              
WM_WINDOWPOSCHANGING   
 WM_GETMINMAXINFO      
WM_NCCALCSIZE          
WM_NCPAINT             
WM_ERASEBKGND          
WM_WINDOWPOSCHANGED    
 WM_MOVE               
 WM_SIZE               
 [WM_WINDOWPOSCHANGING] // not received
 WM_NCCALCSIZE         
 WM_NCPAINT            
 WM_ERASEBKGND         
 [WM_WINDOWPOSCHANGED] // not received
WM_PAINT               
[WM_MOUSEMOVE] // not received

где строки «не получены» - это msgs. Spy ++ сообщает, что окно открывается, но оно никогда не появляется в WndProc! Более того, если я ставлю точку останова в самом начале WndProc, а другую - на вызов DefWindowProc в WM_WINDOWPOSCHANGED, то при переходе через вызов DefWindowProc точка останова в начале WndProc не срабатывает ... это означает, что no msg получает WndProc в результате вызова DefWindowProc в WM_WINDOWPOSCHANGED. Если кто-то не видит что-то, что мне не хватает, Spy ++ не точно отображает сообщения, которые получает ваше окно, а скорее их искаженную версию, как я покажу выше!

Ответы [ 2 ]

0 голосов
/ 17 октября 2011

Я только что продублировал ваш эксперимент, и вот что у меня получилось:

<00494> 000307A6 P WM_MOUSEMOVE fwKeys:MK_LBUTTON xPos:-4 yPos:173
<00495> 000307A6 S WM_SIZING fwSide:WMSZ_LEFT lprc:0012F71C
<00496> 000307A6 R WM_SIZING fProcessed:False
<00497> 000307A6 S WM_WINDOWPOSCHANGING lpwp:0012F710
    <00498> 000307A6 S WM_GETMINMAXINFO lpmmi:0012F36C
    <00499> 000307A6 R WM_GETMINMAXINFO lpmmi:0012F36C
<00500> 000307A6 R WM_WINDOWPOSCHANGING
<00501> 000307A6 S WM_NCCALCSIZE fCalcValidRects:True lpncsp:0012F6E4
<00502> 000307A6 R WM_NCCALCSIZE fuValidRect:0000 lpncsp:0012F6E4
<00503> 000307A6 S WM_NCPAINT hrgn:00000001
    <00504> 000307A6 S WM_GETTEXT cchTextMax:510 lpszText:0012EB68
    <00505> 000307A6 R WM_GETTEXT cchCopied:3 lpszText:0012EB68 ("F")
<00506> 000307A6 R WM_NCPAINT
<00507> 000307A6 S WM_ERASEBKGND hdc:A9010D6B
<00508> 000307A6 R WM_ERASEBKGND fErased:True
<00509> 000307A6 S WM_WINDOWPOSCHANGED lpwp:0012F710
    <00510> 000307A6 S WM_MOVE xPos:141 yPos:218
    <00511> 000307A6 R WM_MOVE
    <00512> 000307A6 S WM_SIZE fwSizeType:SIZE_RESTORED nWidth:991 nHeight:664
    <00513> 000307A6 R WM_SIZE
<00514> 000307A6 R WM_WINDOWPOSCHANGED
<00515> 000307A6 S WM_PAINT hdc:00000000
<00516> 000307A6 R WM_PAINT
<00517> 000307A6 P WM_MOUSEMOVE fwKeys:MK_LBUTTON xPos:-5 yPos:173
<00518> 000307A6 S WM_SIZING fwSide:WMSZ_LEFT lprc:0012F71C
<00519> 000307A6 R WM_SIZING fProcessed:False
<00520> 000307A6 S WM_WINDOWPOSCHANGING lpwp:0012F710
    <00521> 000307A6 S WM_GETMINMAXINFO lpmmi:0012F36C
    <00522> 000307A6 R WM_GETMINMAXINFO lpmmi:0012F36C
<00523> 000307A6 R WM_WINDOWPOSCHANGING
<00524> 000307A6 S WM_NCCALCSIZE fCalcValidRects:True lpncsp:0012F6E4
<00525> 000307A6 R WM_NCCALCSIZE fuValidRect:0000 lpncsp:0012F6E4
<00526> 000307A6 S WM_NCPAINT hrgn:00000001
    <00527> 000307A6 S WM_GETTEXT cchTextMax:510 lpszText:0012EB68
    <00528> 000307A6 R WM_GETTEXT cchCopied:3 lpszText:0012EB68 ("F")
<00529> 000307A6 R WM_NCPAINT
<00530> 000307A6 S WM_ERASEBKGND hdc:A9010D6B
<00531> 000307A6 R WM_ERASEBKGND fErased:True
<00532> 000307A6 S WM_WINDOWPOSCHANGED lpwp:0012F710
    <00533> 000307A6 S WM_MOVE xPos:139 yPos:218
    <00534> 000307A6 R WM_MOVE
    <00535> 000307A6 S WM_SIZE fwSizeType:SIZE_RESTORED nWidth:993 nHeight:664
    <00536> 000307A6 R WM_SIZE
<00537> 000307A6 R WM_WINDOWPOSCHANGED
<00538> 000307A6 S WM_PAINT hdc:00000000
<00539> 000307A6 R WM_PAINT

Это согласуется с документацией MSDN о WM_WINDOWSPOSCHANGED и WM_WINDOWSPOSCHANGING, и, более того, это то, что мы ожидаем.

Итак, ваша версия Spy ++ неверна или ваша Windows делает неприятные вещи.

0 голосов
/ 16 октября 2011

причина, по которой вы испытываете это, заключается в том, что все, что DefWindowProc () будет делать с WM_WINDOWPOSCHANGED, - это добавление событий WM_SIZE и WM_MOVE в очередь сообщений См. Msdn здесь , поэтому этот код:

++lcount;
lReturnValue = DefWindowProc(hWnd, message, wParam, lParam);
--lcount;

просто увеличивает lcount, добавляет сообщения WM_SIZE и WM_MOVE в очередь, затем уменьшает lcount. WM_NCPAINT не будет вызываться между этими двумя операциями на lcount.

Надеюсь, это поможет?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...