gpt4 book ai didi

c++ - 如何在 winApi 上正确创建按钮以及处理其消息

转载 作者:行者123 更新时间:2023-11-28 01:20:52 28 4
gpt4 key购买 nike

所以我的程序可以正常工作,除此之外,我希望我的按钮“pushBtn”(又名 BTN_PUSH_TALK)发送 BN_PUSHED 或 BN_UNPUSHED 消息,以便我可以相应地处理它。

按照在线步骤以及试验和改进,现在我得到的唯一响应是在我完成按住/单击按钮后。

       pushBtn = CreateWindowEx(0, L"BUTTON", L"TALK", WS_CHILD | 
WS_VISIBLE |
BS_DEFPUSHBUTTON , 0 , 290 , 50, 50,
hWnd,(HMENU)BTN_PUSH_TALK, GetModuleHandle(NULL), NULL);

处理程序(或至少重要的):

 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM 
lParam)
{
bool asd;
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);

// Parse the menu selections:
switch (wmId)
{
case BTN_PUSH_TALK:
switch (HIWORD(wParam))
{
case BN_UNPUSHED:
if (connected && inputChoiceStr == "Push To Talk") {
tplug->setDuck(false);
}
break;
case BN_PUSHED:
if (connected && inputChoiceStr == "Push To Talk") {
tplug->setDuck(true);
}
break;
}
break;

我原以为一旦我点击并按住按钮,就会进入 BN_PUSHED 案例,但事实并非如此。放手时,我希望输入 BN_UNPUSHED 案例,但事实也并非如此。达到 BTN_PUSH_TALK 的情况,这意味着按钮是可识别的,但是永远不会达到此代码块中的开关情况。

最佳答案

如果我没看错问题,您的目标是在用户最初按下标准按钮时获得通知,而按钮的标准通知行为仅在“点击”时发布 WM_COMMAND,其中点击是整个鼠标向下加鼠标向上顺序。

过去,为了在 WM_COMMAND 处理程序中获得 BN_PUSHED 和 BN_UNPUSHED 通知,您必须在创建按钮时使用 BS_NOTIFY 窗口样式。但是,如果您阅读 BN_PUSHED 或 BN_UNPUSHED 的文档,您会看到

This notification code is provided only for compatibility with 16-bit versions of Windows earlier than version 3.0. Applications should use the BS_OWNERDRAW button style and the DRAWITEMSTRUCT structure for this task.

这些是非常古老的通知,据我所知,它们不仅已被弃用,甚至不再受支持。但是,您可以按照文档建议的那样做:使用所有者绘制的按钮,即使用 BS_OWNERDRAW 样式创建的按钮。

事实证明,这比仅在打开 BS_NOTIFY 的情况下创建按钮更困难,因为按钮将不再自行执行默认绘制。考虑到这个额外的琐事,我建议不要这样做,除非您无论如何都想自定义绘制您的按钮——除非您碰巧想要这些按钮具有一些非标准的视觉观感以及非标准的通知行为。否则,我可能会像其他人建议的那样进行 Win32 子类化以捕获 WM_LBUTTONDOWN 等,然后在对我关心的事件执行一些操作后调用标准按钮 WNDPROC。

无论如何,报告按钮按下和按钮弹起事件的最小所有者绘制按钮如下所示。 (我将按钮事件作为自定义消息发布,但你可以在那里做任何你想做的事)

#include <windows.h>

#define BTN_ID 101

#define WM_PUSHBUTTONDOWN WM_APP + 1
#define WM_PUSHBUTTONUP WM_APP + 2

HINSTANCE g_instance = 0;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
g_instance = hInstance;

MSG msg = { 0 };
WNDCLASS wc = { 0 };
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_BACKGROUND);
wc.lpszClassName = L"owner_draw_btn";

if (!RegisterClass(&wc))
return -1;

if (!CreateWindow(wc.lpszClassName, L"foobar", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 640, 480, 0, 0, hInstance, NULL))
return -1;

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

return 0;
}

LRESULT HandleDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
auto* dis = reinterpret_cast<DRAWITEMSTRUCT*>(lParam);
if (dis->CtlType != ODT_BUTTON)
return 0;

auto style = (dis->itemState & ODS_SELECTED) ?
DFCS_BUTTONPUSH | DFCS_PUSHED :
DFCS_BUTTONPUSH;

auto rect = &dis->rcItem;
DrawFrameControl(dis->hDC, rect, DFC_BUTTON, style);

TCHAR text[512];
auto n = GetWindowText(dis->hwndItem, text, 512);
DrawText(dis->hDC, text, n, rect, DT_SINGLELINE | DT_VCENTER | DT_CENTER);

if (dis->itemAction == ODA_SELECT) {
PostMessage(
hWnd,
(dis->itemState & ODS_SELECTED) ? WM_PUSHBUTTONDOWN : WM_PUSHBUTTONUP,
dis->CtlID,
0
);
}
return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
CreateWindow(
L"button", L"foobar",
BS_OWNERDRAW | WS_CHILD | WS_VISIBLE,
10, 10, 150, 35, hWnd,
(HMENU) BTN_ID,
g_instance,
0
);
return 0;

case WM_DRAWITEM:
return HandleDrawItem(hWnd, wParam, lParam);

case WM_PUSHBUTTONDOWN:
OutputDebugString(L"Button down event\n");
break;

case WM_PUSHBUTTONUP:
OutputDebugString(L"Button up event\n");
break;

case WM_CLOSE:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}

关于c++ - 如何在 winApi 上正确创建按钮以及处理其消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56343774/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com