对编辑控件进行子类化(在完整窗口中,不对话)

时间:2013-08-01 08:24:23

标签: c++ winapi controls subclassing

我一直在努力解决这个问题很长时间,我绝对难过!我正在尝试子类化编辑控件,以便在按下回车键时捕获。

我已经看到很多关于使用代码片段进行子类化的其他帖子来添加它,但我似乎无法将其实现到我的应用程序中。如果我犯了一个愚蠢的错误,我道歉,但我根本无法解决这个问题。

我知道这段代码编写得很糟糕且没有错误检查,但我希望发布尽可能少的代码来传达问题。

#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;
}

1 个答案:

答案 0 :(得分:0)

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

更糟糕的是,即使您正确地对“编辑”窗口进行子类化,也会在设置后立即删除子类。所以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;
}