【问题标题】:Subclassed Control only Recieving Parent Messages仅接收父消息的子类控件
【发布时间】:2014-06-14 07:28:42
【问题描述】:

我有三个位于父窗口顶部的控件。 一个接受用户输入,而另一个显示以前的输入。第三个是将文本从输入编辑控件附加到输出控件的按钮。但是,由于这样做很麻烦,我想为“enter”键添加一个句柄来执行此操作。目前,我已经对输入编辑控件进行了子类化。但是,无论我实现哪种 switch 语句配置,我都无法从 Input 控件中获得要解释的“WM_KeyDown”消息。但是,如果父控件处于焦点状态,则它是从父控件发送的。它不是从编辑控件发送的,即使在焦点上也是如此。我已经找到了几种解决方案,但到目前为止它们都不起作用。

任何帮助将不胜感激!

Win32 C++、Visual Studio 2012

#include <Windows.h>
#include <string.h>
#include <tchar.h>
#include <stdlib.h>
#include <Commctrl.h>

#include "resource.h"
#include "Processing.h"

static TCHAR WinClass[]=_T("SAPA");
static TCHAR WinTitle[]=_T("SAPA");

HWND InText, OutText, Send;
LPWSTR string;

LPTSTR buff = new TCHAR [1024];
LPTSTR Tbuff = new TCHAR [1024];

HINSTANCE hInst;

syscore sysCore;

WNDPROC DefProc;
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
DWORD dwRefData;
UINT uIdSubClass;

int WINAPI WinMain(HINSTANCE hIn, HINSTANCE hpIn, LPSTR CmdLine, int CmdShow)
{
WNDCLASSEX wcex;

wcex.cbSize         =   sizeof(WNDCLASSEX);
wcex.style          =   CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc    =   WndProc;
wcex.cbClsExtra     =   0;
wcex.cbWndExtra     =   0;
wcex.hInstance      =   hIn;
wcex.hIcon          =   LoadIcon(hIn,MAKEINTRESOURCE(APP_ICO));
wcex.hCursor        =   LoadCursor(NULL,IDC_ARROW);
wcex.hbrBackground  =   (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName   =   L"IDC_WINMENU";
wcex.lpszClassName  =   WinClass;
wcex.hIconSm            =   LoadIcon(wcex.hInstance, MAKEINTRESOURCE(APP_ICO));

if (!RegisterClassEx(&wcex))
{
    MessageBox(NULL,_T("RegClassEx Failure"),_T("ERROR"),NULL);
    return 1;
}

hInst=hIn;

HWND hwnd=CreateWindow(WinClass, WinTitle,WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, 800,650,NULL,NULL, hIn,NULL);

if (!hwnd)
{
    MessageBox(NULL,_T("CreateWindow Failuer"),_T("ERROR"),NULL);
    return 1;
}

ShowWindow(hwnd, CmdShow);

UpdateWindow(hwnd);

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

return (int) msg.wParam;

}

LRESULT CALLBACK InEditControlProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
//  if (LOWORD(wp)==IDM_IN)
    switch(msg) {
    case WM_COMMAND:
        if (LOWORD(wp)==IDM_IN)
            if (HIWORD(wp)==WM_KEYDOWN)
                if (HIWORD(lp)==VK_LCONTROL)
                    PostQuitMessage(0);
        break;
        case WM_KEYDOWN: {
        switch (wp) {
            case VK_RETURN: {
                PostQuitMessage(0);
                    //simulate a button press, see below
                   // return 0;//if the procedure responds the action, finish the control procedure
                    break;
                }
                break;
            }
        }
        break;
            //return CallWindowProc(WndProc,hwnd,msg,wp,lp);//WndProc(hwnd,msg,wp,lp);
        default:
        return CallWindowProc(WndProc,hwnd,msg,wp,lp);//WndProc(hwnd,msg,wp,lp);
        //return WndProc(hwnd,msg,wp,lp);
    }
    return 0;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
    int len=0;
    //LPCWSTR buffer=L"";
    switch (msg)
    {
    case WM_CREATE:
        OutText=CreateWindow(L"edit", L"",ES_READONLY|ES_MULTILINE|WS_CHILD|WS_VISIBLE|WS_BORDER|ES_AUTOVSCROLL, 0, 0, 800,550,hwnd,(HMENU)IDM_OUT, NULL,NULL);
        InText=CreateWindow(L"edit", L"",WS_CHILD|WS_VISIBLE|WS_BORDER, 0, 550, 720,50,hwnd,(HMENU)IDM_IN, NULL,NULL);
        Send=CreateWindow(L"button", L"SEND",WS_CHILD|WS_VISIBLE|WS_BORDER, 720, 550, 80,25,hwnd,(HMENU)MSG_SEND, NULL,NULL);
        CreateWindow(L"button", L"CLEAR",WS_CHILD|WS_VISIBLE|WS_BORDER, 720, 575, 80,25,hwnd,(HMENU)IDM_CLEAR, NULL,NULL);

        //DefProc = (WNDPROC)GetWindowLong(hwnd,GWL_WNDPROC);
        //SetWindowLong(hwnd,GWL_WNDPROC,(LONG_PTR)InEditControlProc);
        DefProc=(WNDPROC)SetWindowLongPtr(hwnd,GWLP_WNDPROC,(LONG_PTR)InEditControlProc);
        //SetWindowSubclass(hwnd,InEditControlProc,uIdSubClass,dwRefData);
        ShowWindow(InText,SW_SHOW);
        SetFocus(InText);

        startup(hwnd,OutText,InText,sysCore);
        break;
    case WM_DESTROY:
        SetWindowLongPtr(hwnd,GWLP_WNDPROC,(LONG_PTR)WndProc);
        PostQuitMessage(0);
        break;
    case WM_COMMAND:

        switch (LOWORD(wp))
        {
        case MSG_SEND:
            //TCHAR buff[1024];
            buff = new TCHAR [1024];
            Tbuff = new TCHAR [1024];
            GetWindowText(GetDlgItem(hwnd,IDM_IN),buff,1024);//get text from box, store to buffer
            GetWindowText(GetDlgItem(hwnd,IDM_OUT),Tbuff,1024);//retain window text
            SetWindowText(GetDlgItem(hwnd,IDM_IN),L"");//clear field
            if (buff!=L"")//dont pass if buffer empty
            {
            AppendText(hwnd,buff);
            AppendText(hwnd,L"\r\n");
            }
            handleInput(hwnd,buff,sysCore);
            //SetWindowText(GetDlgItem(hWnd,OFIELD),buff);//set text
            delete buff,Tbuff;
            break;
        case IDM_CLEAR:
            SetWindowText(GetDlgItem(hwnd,IDM_OUT),L"");
            break;
        case IDM_ABOUT:
            MessageBox(hwnd,L"App information",L"About",0);
            break;
        case IDM_EXIT:
            PostQuitMessage(0);
        }

    default:
        return DefWindowProc(hwnd, msg,wp,lp);
        break;
    }
    return 0;
}

【问题讨论】:

  • 如果您看到应该发送给父级的消息,那么您首先考虑的可能是您对错误的窗口进行了子分类。因此,您查看传递给 SetWindowLongPtr() 的窗口句柄。那不是 InText。
  • 不是吗?传递给 SetWindowLongPtr() 的 LONG_PTR 参数是专用于 InText 窗口的 HMENU。如果您的意思是将 hwnd 参数设置为 InText,那么就会产生 InText 窗口被禁用的问题,这最终会阻止它发送信号。

标签: c++ event-handling message subclass subclassing


【解决方案1】:

好的,经过几天的环顾,我想通了,这在很大程度上是为了学习使用 spy++ 实用程序。

发现子类化后,添加一行

if(msg.message==WM_KEYDOWN)
     SendMessage(hwnd,msg.message,msg.wParam,msg.lParam);

在 Translate/DispatchMessage 之后的消息泵中允许这些自定义信号 路由到正确的程序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-27
    • 1970-01-01
    • 2020-01-04
    • 2010-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-17
    相关资源
    最近更新 更多