0

多年来我一直试图弄清楚这一点,我完全被难住了!我正在尝试对编辑控件进行子类化,以便在按下回车键时进行捕获。

我已经看到很多其他关于使用代码片段进行子类化的帖子,但我似乎无法在我的应用程序中实现它。如果我犯了一个愚蠢的错误,我深表歉意,但我根本无法弄清楚。

我知道这段代码写得不好并且没有错误检查,但我想发布尽可能少的代码来传达问题。

#include <Windows.h>
#include <wchar.h>

HWND editHWND;
WNDPROC wpOrigEditProc;

LRESULT APIENTRY EditSubclassProc(HWND hwnd,UINT uMsg,WPARAM wParam, LPARAM lParam)
{
    if (uMsg == WM_CHAR)
    {
        //do my stuff
    }
    return CallWindowProc(wpOrigEditProc, hwnd, uMsg, wParam, lParam);
}


LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
    case WM_CREATE:

        wpOrigEditProc = (WNDPROC) SetWindowLong(editHWND,GWL_WNDPROC, (LONG) EditSubclassProc);
        SetWindowLong(editHWND, GWL_WNDPROC,(LONG) wpOrigEditProc);
        break;

    case WM_DESTROY:
        PostQuitMessage( 0 );
        return 0;
    }

    return DefWindowProc( hWnd, msg, wParam, lParam );
}

int WINAPI wWinMain( HINSTANCE hInst,HINSTANCE,LPWSTR,INT )
{
    WNDCLASSEX wc = { sizeof( WNDCLASSEX ),CS_CLASSDC,MsgProc,0,0,
                      GetModuleHandle( NULL ),NULL,NULL,NULL,NULL,
                      L"My Window",NULL };
    RegisterClassEx( &wc );

    HWND hWnd = CreateWindowW( L"My Window",L"test application",
                              WS_OVERLAPPEDWINDOW,100,100,800,600,
                              NULL,NULL,wc.hInstance,NULL );

    editHWND = CreateWindow( L"edit",L"hi there",WS_VISIBLE | WS_CHILD | WS_BORDER,100,100,300,50,hWnd,(HMENU)17,0,0);

    ShowWindow( hWnd,SW_SHOWDEFAULT );

    MSG msg;
    ZeroMemory( &msg,sizeof( msg ) );
    while( msg.message != WM_QUIT )
    {
        if( PeekMessage( &msg,NULL,0,0,PM_REMOVE ) )
        {
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
    }

    UnregisterClass( L"My Window",wc.hInstance );
    return 0;
}
4

1 回答 1

0

MsgProc()是“我的窗口”窗口的窗口过程。在处理WM_CREATE消息时,您正在处理该窗口的创建,然后CreateWindow()调用第二个窗口来创建编辑窗口。

更糟糕的是,即使您正确地对 Edit 窗口进行子类化,您也会在设置后立即删除子类。所以EditSubClassProc()无论如何都不会有任何改变。

由于在创建编辑窗口时您没有为编辑窗口定义自定义窗口过程,因此您不能使用WM_CREATE消息来子类化编辑窗口(除非您使用消息挂钩,这在这种情况下是多余的)。退出SetWindowLong()后调用即可。CreateWindow()

尝试这个:

#include <Windows.h>
#include <wchar.h>

HWND editHWND = NULL;
WNDPROC wpOrigEditProc = NULL;

LRESULT APIENTRY EditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    if (uMsg == WM_CHAR)
    {
        //do my stuff
    }
    return CallWindowProc(wpOrigEditProc, hwnd, uMsg, wParam, lParam);
}

LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
    case WM_CLOSE:
        DestroyWindow(hWnd);
        return 0;

    case WM_DESTROY:
        PostQuitMessage( 0 );
        return 0;
    }

    return DefWindowProc( hWnd, msg, wParam, lParam );
}

int WINAPI wWinMain( HINSTANCE hInst,HINSTANCE,LPWSTR,INT )
{
    WNDCLASSEX wc = { sizeof( WNDCLASSEX ),CS_CLASSDC,MsgProc,0,0,
                      GetModuleHandle( NULL ),NULL,NULL,NULL,NULL,
                      TEXT("My Window"),NULL };
    RegisterClassEx( &wc );

    HWND hWnd = CreateWindowW( TEXT("My Window"),TEXT("test application"),
                              WS_OVERLAPPEDWINDOW,100,100,800,600,
                              NULL,NULL,wc.hInstance,NULL );

    editHWND = CreateWindow( TEXT("edit"),TEXT("hi there"),WS_VISIBLE | WS_CHILD | WS_BORDER,100,100,300,50,hWnd,(HMENU)17,0,0);

    wpOrigEditProc = (WNDPROC) SetWindowLongPtr(editHWND, GWL_WNDPROC, (LONG_PTR) EditSubclassProc);

    ShowWindow( hWnd, SW_SHOWDEFAULT );

    MSG msg;
    while ( GetMessage( &msg,NULL,0,0 ) > 0 )
    {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }

    UnregisterClass( TEXT("My Window"),wc.hInstance );
    return 0;
}

话虽如此,另一种子类化窗口的方法是使用SetWindowSubclass()

#include <Windows.h>
#include <wchar.h>

HWND editHWND = NULL;

LRESULT CALLBACK EditSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    if (uMsg == WM_CHAR)
    {
        //do my stuff
    }

    return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}

LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
    case WM_CLOSE:
        DestroyWindow(hWnd);
        return 0;

    case WM_DESTROY:
        PostQuitMessage( 0 );
        return 0;
    }

    return DefWindowProc( hWnd, msg, wParam, lParam );
}

int WINAPI wWinMain( HINSTANCE hInst,HINSTANCE,LPWSTR,INT )
{
    WNDCLASSEX wc = { sizeof( WNDCLASSEX ),CS_CLASSDC,MsgProc,0,0,
                      GetModuleHandle( NULL ),NULL,NULL,NULL,NULL,
                      TEXT("My Window"),NULL };
    RegisterClassEx( &wc );

    HWND hWnd = CreateWindowW( TEXT("My Window"),TEXT("test application"),
                              WS_OVERLAPPEDWINDOW,100,100,800,600,
                              NULL,NULL,wc.hInstance,NULL );

    editHWND = CreateWindow( TEXT("edit"),TEXT("hi there"),WS_VISIBLE | WS_CHILD | WS_BORDER,100,100,300,50,hWnd,(HMENU)17,0,0);

    SetWindowSubclass(editWND, EditSubclassProc, 0, 0);

    ShowWindow( hWnd, SW_SHOWDEFAULT );

    MSG msg;
    while ( GetMessage( &msg,NULL,0,0 ) > 0 )
    {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }

    UnregisterClass( TEXT("My Window"),wc.hInstance );
    return 0;
}
于 2013-08-01T18:32:49.637 回答