C++ 触发WM_命令时,为什么WM_按键不起作用?

C++ 触发WM_命令时,为什么WM_按键不起作用?,c++,user-interface,winapi,C++,User Interface,Winapi,当我在客户端窗口中单击按钮,然后按下向下箭头键时,WM_KEYDOWN不会发送到我的windows过程,但其他情况总是有效的,因此要解决此问题,我必须在客户端窗口外单击,然后在客户端窗口中单击(但不是按钮),然后WM_KEYDOWN将有效,有没有更好的方法来停止我按钮的焦点 代码如下: #include <iostream> #define _WIN32_WINNT 0x0501 #include <Windows.h> #include <winuser.h>

当我在客户端窗口中单击按钮,然后按下向下箭头键时,WM_KEYDOWN不会发送到我的windows过程,但其他情况总是有效的,因此要解决此问题,我必须在客户端窗口外单击,然后在客户端窗口中单击(但不是按钮),然后WM_KEYDOWN将有效,有没有更好的方法来停止我按钮的焦点

代码如下:

#include <iostream>
#define _WIN32_WINNT 0x0501
#include <Windows.h>
#include <winuser.h>
#include <vector>
#include<string>
using namespace std;

const char* className = "MyCLASSNAME!";

HWND hButton;
RECT rect;
POINT p = {0, 0};

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{


    switch(msg)
    {
    case WM_CREATE:

        hButton = CreateWindow(TEXT("BUTTON"), TEXT("1"), WS_VISIBLE | WS_CHILD, 8, 41, 50, 50, hWnd, (HMENU)1, NULL, NULL);
        break;

    case WM_KEYDOWN:

        switch (wParam)
        {

        case VK_DOWN:

            if(GetWindowRect(hButton, &rect))
            {
                POINT p1 = {rect.left, rect.top};
                ScreenToClient(hWnd, &p1);
                SetWindowPos(hButton, NULL, p1.x, p1.y, rect.right - rect.left + 1, rect.bottom - rect.top + 1, SWP_SHOWWINDOW);

            }

            break;
        }

        break;
    case WM_LBUTTONDOWN:
        GetCursorPos( &p );


        GetClientRect(hButton, &rect);
        SetWindowPos(hButton, NULL, p.x, p.y - 22, rect.right, rect.bottom, SWP_SHOWWINDOW);
        break;
    case WM_COMMAND:


        switch(LOWORD(wParam))
        {
        case 1:
            break;
        }

        break;

    case WM_CLOSE:
        DestroyWindow(hWnd);
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;

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

    return 0;
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{

    WNDCLASSEXA wc;
    HWND hWnd;
    MSG msg;

    wc.cbClsExtra = 0;
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.cbWndExtra = 0;
    wc.hbrBackground = CreateSolidBrush(RGB(0,0,0));
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    wc.hInstance = hInstance;
    wc.lpfnWndProc = WndProc;
    wc.lpszClassName = className;
    wc.lpszMenuName = "MENU!";
    wc.style = NULL;

    RegisterClassEx(&wc);

    hWnd = CreateWindowEx(WS_EX_LAYERED, className, "hello", WS_OVERLAPPEDWINDOW, 0, 0, 500, 500, NULL, NULL, hInstance, NULL);
    SetLayeredWindowAttributes(hWnd, 0, 255, LWA_ALPHA);

    ShowWindow(hWnd, nShowCmd);
    UpdateWindow(hWnd);

    while(GetMessage(&msg, hWnd, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);


    }


    return msg.wParam;
}
#包括
#定义_WIN32_WINNT 0x0501
#包括
#包括
#包括
#包括
使用名称空间std;
const char*className=“MyCLASSNAME!”;
HWND按钮;
RECT-RECT;
点p={0,0};
LRESULT回调WndProc(HWND HWND,UINT msg,WPARAM WPARAM,LPARAM LPARAM)
{
开关(msg)
{
案例WM_创建:
hButton=CreateWindow(文本(“按钮”)、文本(“1”)、可见的窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口窗口;
打破
案例WM_键控:
交换机(wParam)
{
案例VK_下降:
if(GetWindowRect(hButton和rect))
{
点p1={rect.left,rect.top};
屏幕客户端(hWnd和p1);
设置窗口位置(hButton,NULL,p1.x,p1.y,rect.right-rect.left+1,rect.bottom-rect.top+1,SWP_显示窗口);
}
打破
}
打破
案例WM_LBUTTONDOWN:
GetCursorPos&p;
GetClientRect(hButton和rect);
SetWindowPos(hButton,NULL,p.x,p.y-22,rect.right,rect.bottom,SWP_SHOWWINDOW);
打破
case WM_命令:
开关(LOWORD(wParam))
{
案例1:
打破
}
打破
案例WM_结束:
窗口(hWnd);
打破
案例WM_销毁:
PostQuitMessage(0);
打破
违约:
返回DefWindowProc(hWnd、msg、wParam、lParam);
}
返回0;
}
int APIENTRY WinMain(HINSTANCE HINSTANCE、HINSTANCE hPrevInstance、LPSTR lpCmdLine、int nShowCmd)
{
Wndclassaxa wc;
HWND-HWND;
味精;
wc.cbClsExtra=0;
wc.cbSize=sizeof(WNDCLASSEX);
wc.cbWndExtra=0;
wc.hbrBackground=CreateSolidBrush(RGB(0,0,0));
wc.hCursor=LoadCursor(空,IDC_箭头);
wc.hIcon=LoadIcon(空,IDI_应用程序);
wc.hIconSm=LoadIcon(空,IDI_应用程序);
wc.hInstance=hInstance;
wc.lpfnWndProc=WndProc;
wc.lpszClassName=className;
wc.lpszMenuName=“菜单!”;
wc.style=NULL;
注册类别(&wc);
hWnd=CreateWindowEx(WS_EX_分层,类名,“hello”,WS_重叠窗口,0,0,500,500,NULL,NULL,hInstance,NULL);
SetLayeredWindowAttributes(hWnd、0、255、LWA_ALPHA);
显示窗口(hWnd、nShowCmd);
更新窗口(hWnd);
while(GetMessage(&msg,hWnd,0,0)>0)
{
翻译信息(&msg);
发送消息(&msg);
}
返回msg.wParam;
}

原因是,当您按下按钮时,您的注意力集中在当前按钮上,因此您的
WM_KEYDOWN
消息会发送到该按钮

因此,您需要对按钮进行子类化,并处理按钮的
WM_KEYDOWN
消息

以下是修改后的示例:

#include <iostream>
#define _WIN32_WINNT 0x0501
#include <Windows.h>
#include <winuser.h>
#include <vector>
#include <string>
#include <CommCtrl.h>
using namespace std;

const char* className = "MyCLASSNAME!";
HWND hWnd;
HWND hButton;
RECT rect;
POINT p = { 0, 0 };
WNDPROC ButtonOldProc;

LRESULT CALLBACK ButtonProcNew(HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    switch (message)
    {
    case WM_KEYDOWN:
        switch (wParam)
        {
        case VK_DOWN:

            if (GetWindowRect(hButton, &rect))
            {
                POINT p1 = { rect.left, rect.top };
                ScreenToClient(hWnd, &p1);
                SetWindowPos(hButton, NULL, p1.x, p1.y, rect.right - rect.left + 1, rect.bottom - rect.top + 1, SWP_SHOWWINDOW);
            }
            break;
        }
        break;
    default:
        return DefSubclassProc(hwnd, message, wParam, lParam);
    }
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_CREATE:

        hButton = CreateWindow(TEXT("BUTTON"), TEXT("1"), WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 8, 41, 50, 50, hWnd, (HMENU)1, NULL, NULL);
        SetWindowSubclass(hButton, ButtonProcNew, 0, 0);
        break;

    case WM_KEYDOWN:
        switch (wParam)
        {
        case VK_DOWN:

            if (GetWindowRect(hButton, &rect))
            {
                POINT p1 = { rect.left, rect.top };
                ScreenToClient(hWnd, &p1);
                SetWindowPos(hButton, NULL, p1.x, p1.y, rect.right - rect.left + 1, rect.bottom - rect.top + 1, SWP_SHOWWINDOW);
            }
            break;
        }

        break;
    case WM_LBUTTONDOWN:
        GetCursorPos(&p);
        GetClientRect(hButton, &rect);
        SetWindowPos(hButton, NULL, p.x, p.y - 22, rect.right, rect.bottom, SWP_SHOWWINDOW);
        break;
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case 1:
            break;
        }
        break;
    case WM_CLOSE:
        DestroyWindow(hWnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }

    return 0;
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{

    WNDCLASSEXA wc;
    MSG msg;
    wc.cbClsExtra = 0;
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.cbWndExtra = 0;
    wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    wc.hInstance = hInstance;
    wc.lpfnWndProc = WndProc;
    wc.lpszClassName = className;
    wc.lpszMenuName = "MENU!";
    wc.style = NULL;
    RegisterClassEx(&wc);
    hWnd = CreateWindowEx(WS_EX_LAYERED, className, "hello", WS_OVERLAPPEDWINDOW, 0, 0, 500, 500, NULL, NULL, hInstance, NULL);
    SetLayeredWindowAttributes(hWnd, 0, 255, LWA_ALPHA);
    ShowWindow(hWnd, nShowCmd);
    UpdateWindow(hWnd);

    while (GetMessage(&msg, hWnd, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
#包括
#定义_WIN32_WINNT 0x0501
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
const char*className=“MyCLASSNAME!”;
HWND-HWND;
HWND按钮;
RECT-RECT;
点p={0,0};
WNDPROC ButtolDPROC;
LRESULT回调按钮POCNEW(HWND HWND,UINT消息,WPARAM WPARAM,LPARAM LPARAM,UINT_PTR uIdSubclass,DWORD_PTR dwRefData)
{
开关(信息)
{
案例WM_键控:
交换机(wParam)
{
案例VK_下降:
if(GetWindowRect(hButton和rect))
{
点p1={rect.left,rect.top};
屏幕客户端(hWnd和p1);
设置窗口位置(hButton,NULL,p1.x,p1.y,rect.right-rect.left+1,rect.bottom-rect.top+1,SWP_显示窗口);
}
打破
}
打破
违约:
返回defsublassproc(hwnd、message、wParam、lParam);
}
}
LRESULT回调WndProc(HWND HWND,UINT msg,WPARAM WPARAM,LPARAM LPARAM)
{
开关(msg)
{
案例WM_创建:
hButton=CreateWindow(文本(“按钮”)、文本(“1”)、WS|u可见| WS|u子项| BS|u解除按钮、8、41、50、50、hWnd、(HMENU)1、空、空);
SetWindowsSubClass(hButton,ButtonProcNew,0,0);
打破
案例WM_键控:
交换机(wParam)
{
案例VK_下降:
if(GetWindowRect(hButton和rect))
{
点p1={rect.left,rect.top};
屏幕客户端(hWnd和p1);
设置窗口位置(hButton,NULL,p1.x,p1.y,rect.right-rect.left+1,rect.bottom-rect.top+1,SWP_显示窗口);
}
打破
}
打破
案例WM_LBUTTONDOWN:
GetCursorPos&p;
GetClientRect(hButton和rect);
SetWindowPos(hButton,NULL,p.x,p.y-22,rect.right,rect.bottom,SWP_SHOWWINDOW);
打破
case WM_命令:
开关(LOWORD(wParam))
{
案例1:
打破
}
打破
案例WM_结束:
窗口(hWnd);
打破
案例WM_销毁:
PostQuitMessage(0);
打破
违约:
返回DefWindowProc(hWnd、msg、wParam、lParam);
}
返回0;
}
int APIENTRY WinMain(HINSTANCE HINSTANCE、HINSTANCE hPrevInstance、LPSTR lpCmdLine、int nShowCmd)
{
Wndclassaxa wc;
味精;
wc.cbClsExtra=0;
wc.cbSize=sizeof(WNDCLASSEX);
wc.cbWndExtra=0;
wc.hbrBackground=CreateSolidBrush(RGB(0,0,0));
wc.hCursor=LoadCursor(空,IDC_箭头);
wc.hIcon=LoadIcon(空,IDI_应用程序);
wc.hIconSm=LoadIcon(空,IDI_应用程序);
wc.hInstance=hInstance;
wc.lpfnWndProc=WndProc;
wc.lpszClassName=className;
wc.lpszMenuName=“菜单!”;
wc.style=NULL;
注册类别(&wc);
hWnd=CreateWindowEx(WS_EX_分层,clas