- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我想在单击将成为主窗口子项的菜单项时使用 CreateWindow() 创建一个窗口。我知道我可以使用 DialogBox() 或 CreateDialog(),但我想使用 CreateWindow()。我正在使用这段代码
资源.rc文件
#include "resource.h"
IDM_MENU MENU
{
POPUP "&Help"
{
MENUITEM "&About", IDM_HELP
}
}
关于窗口过程
LRESULT CALLBACK AboutProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
主窗口程序
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDM_HELP:
{
WNDCLASSEX wc;
HWND hDlg;
MSG msg;
SecureZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = (HICON)GetClassLong(hwnd, GCL_HICON);
wc.hIconSm = (HICON)GetClassLong(hwnd, GCL_HICONSM);
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = AboutProc;
wc.lpszClassName = TEXT("AboutClass");
if(!RegisterClassEx(&wc))
break;
hDlg = CreateWindowEx(0, wc.lpszClassName, TEXT("About"), WS_OVERLAPPEDWINDOW, 0, 0, 300, 200, hwnd, 0, wc.hInstance, 0);
ShowWindow(hDlg, SW_SHOWNORMAL);
while(GetMessage(&msg, 0, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnregisterClass(wc.lpszClassName, wc.hInstance);
}
break;
}
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
这是个好主意吗?您可以将多个类注册到同一个实例吗?另外,将主窗口图标分配给这个子窗口是个好主意还是我应该每次都加载它们?当我在 IDM_HELP 中调用 UnregisterClass() 时,这些图标会被删除吗?我试过这个程序,一切正常,在我关闭这个子窗口后,图标仍然显示在主窗口中。但是我仍然想知道是否可以将主窗口图标分配给这个窗口,因为我在子窗口关闭后调用了 UnregisterClass()
最佳答案
使用 CreateWindow/Ex()
而不是 CreateDialog()
/DialogBox()
没有任何问题。运行您自己的模态消息循环没有任何问题,只要您正确地实现它。例如,请注意此警告:
Modality, part 3: The WM_QUIT message
The other important thing about modality is that a WM_QUIT message always breaks the modal loop. Remember this in your own modal loops! If ever you call the PeekMessage function or the GetMessage function and get a WM_QUIT message, you must not only exit your modal loop, but you must also re-generate the WM_QUIT message (via the PostQuitMessage message) so the next outer layer will see the WM_QUIT message and do its cleanup as well. If you fail to propagate the message, the next outer layer will not know that it needs to quit, and the program will seem to "get stuck" in its shutdown code, forcing the user to terminate the process the hard way.
您展示的示例没有这样做,因此您需要添加它:
ShowWindow(hDlg, SW_SHOWNORMAL);
do
{
BOOL bRet = GetMessage(&msg, 0, 0, 0);
if (bRet > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
if (bRet == 0)
PostQuitMessage(msg.wParam); // <-- add this!
break;
}
}
while (1);
UnregisterClass(wc.lpszClassName, wc.hInstance);
但是,您的模态窗口不应该使用 WM_QUIT
来打破它的模态循环,因为这样做会退出您的整个应用程序!使用不同的信号使您的模态循环在窗口关闭时中断。例如:
ShowWindow(hDlg, SW_SHOWNORMAL);
while (IsWindow(hDlg) && (GetMessage(&msg, 0, 0, 0) > 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
LRESULT CALLBACK AboutProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
此外,模态窗口应该禁用其所有者窗口,然后在关闭时重新启用它。您的示例也没有这样做,因此也需要添加:
ShowWindow(hDlg, SW_SHOWNORMAL);
EnableWindow(hwnd, FALSE); // <-- add this
...
LRESULT CALLBACK AboutProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CLOSE:
EnableWindow(GetWindow(hwnd, GW_OWNER), TRUE); // <-- add this
DestroyWindow(hwnd);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
Old New Thing博客有一系列关于如何使用模态窗口的文章。
Modality, part 1: UI-modality vs code-modality
Modality, part 2: Code-modality vs UI-modality
Modality, part 3: The WM_QUIT message
Modality, part 4: The importance of setting the correct owner for modal UI
Modality, part 5: Setting the correct owner for modal UI
Modality, part 6: Interacting with a program that has gone modal
Modality, part 7: A timed MessageBox, the cheap version
Modality, part 8: A timed MessageBox, the better version
Modality, part 9: Setting the correct owner for modal UI, practical exam
The correct order for disabling and enabling windows
Make sure you disable the correct window for modal UI
更新:根据您的评论“不,我不想要模态窗口”,您可以忽略上述所有内容。所有这些仅适用于模态窗口。由于您不需要模态窗口,只需完全删除辅助循环并让主消息循环处理所有内容。此外,您不需要调用 UnregisterClass()
。当进程结束时,它将自动注销。调用 RegisterClass()
一次,可以在程序启动时调用,或者至少在您第一次显示“关于”窗口时调用。您可以使用 GetClassInfo/Ex()
来了解该类是否已注册,或自行跟踪。想一想如果用户想要在进程的生命周期内多次显示“关于”窗口会发生什么。因此,让它每次都重新使用现有的类注册。
试试这个:
LRESULT CALLBACK AboutProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDM_HELP:
{
WNDCLASSEX wc = {0};
wc.cbSize = sizeof(WNDCLASSEX);
wc.hInstance = GetModuleHandle(0);
wc.lpszClassName = TEXT("AboutClass");
if (!GetClassInfoEx(wc.hInstance, wc.lpszClassName, &wc))
{
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = (HICON)GetClassLong(hwnd, GCL_HICON);
wc.hIconSm = (HICON)GetClassLong(hwnd, GCL_HICONSM);
wc.lpfnWndProc = AboutProc;
if (!RegisterClassEx(&wc))
break;
}
HWND hDlg = CreateWindowEx(0, wc.lpszClassName, TEXT("About"), WS_OVERLAPPEDWINDOW, 0, 0, 300, 200, hwnd, 0, wc.hInstance, 0);
if (hDlg)
ShowWindow(hDlg, SW_SHOWNORMAL);
}
break;
}
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
关于单击菜单命令时使用 createwindow() 创建窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29359160/
我无法创建自己的名为 CreateWindow 的函数,因为 win32 header 中已经定义了一个函数。只是我什至不能在我自己的命名空间中这样做。真正的问题是什么? MyNamespace::M
我刚刚开始使用 C++ 和创建窗口(在 Windows 上)。我正在使用 CreateWindow 函数,但出现错误 Error 2 error C2664: 'HWND CreateWind
我为我正在编写的 GUI 系统编写了一个主窗口类。在主窗口的构造函数中,它使用 CreateWindow() 函数创建一个 Windows 窗口。该窗口按预期正常显示,但我无法捕获标题栏并将其在屏幕上
在我的 Windows 应用程序中,我正在使用 CreateWindow() 函数创建一个新窗口。注册和创建窗口如下: // Set up the capture window WNDCLASS wc
我想在单击将成为主窗口子项的菜单项时使用 CreateWindow() 创建一个窗口。我知道我可以使用 DialogBox() 或 CreateDialog(),但我想使用 CreateWindow(
我开始使用 C++ 中的 win32 api,当我正要制作一个按钮时,智能感知显示“定义 CreateWindow CreateWindowA”。当我似乎悬停在下方时,它还会显示“错误:预期为 )”。
我正在为 OpenGL 开发一个可移植层(为 Linux 和 Windows 抽象出 glX 和 wgl 的东西)...无论如何,它有一个创建窗口的方法...如果你不传入父级,你会得到一个带框架的真实
您好,我想更改按钮的背景颜色。这是我的按钮代码 hwndTemp = CreateWindow(TEXT("BUTTON"), Str("Settings"), WS_CHILDWINDOW
我对 C++ 相当陌生,并且正在尝试学习在使用 CreateWindow(或 CreateWindowEx)函数为注册类创建的窗口上获取自定义填充颜色的最佳方法。 我编写了一个程序,演示了 3 种方法
您好,我想更改按钮的背景颜色。这是我的按钮代码 hwndTemp = CreateWindow(TEXT("BUTTON"), Str("Settings"), WS_CHILDWINDOW
我在使用 WINAPI 项目时遇到问题。有两个问题,当我用下面的代码启动一个窗口时,高度参数表现得很奇怪。它似乎以 1092 为上限,比我在计算机上需要的位置低 18 个像素。第二个问题是窗口没有边缘
在尝试用 C++ 创建窗口并绘制窗口大小与我设置的大小不匹配的矩形时,我注意到一些非常烦人的事情。 例如,如果我设置 480x240 窗口并尝试通过获取 GetWindowRect(hwnd, &re
我正在使用纯 Win32 API(RegisterClass 和 CreateWindow 函数)创建窗口。如何为窗口指定一种字体而不是系统定义的字体? 最佳答案 当您创建自己的窗口类时,您有责任自己
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Windows Taskbar API Win32: How to hide 3rd party windo
我创建了一个句柄为 handle_parent 的窗口。然后我创建了一个子窗口如下: hwnd_child = CreateWindow(child_class_name, _T(""), WS_CH
我的任务是重新创建具有类似于 Windows 截图工具功能的应用程序。其中之一是捕获当前事件窗口的屏幕截图,这就是导致我出现问题的原因。一切都几乎完美无缺,但是应用程序的“截图”比实际应用程序大几个像
在我的应用程序中,函数 CreateWindow 由于某种原因失败了。 GetLastError 表示错误 1407,根据 MSDN 文档,这是“找不到窗口类”。以下代码显示了如何调用 CreateW
我创建了一个 Electron 应用程序,主要是一个 Web 应用程序,与 Electron 应用程序有少量集成。大多数只是通过带有 loadURL 的 BrowserWindow 加载网站。 但是,
我的程序有一个静态界面,但我不知道制作界面的最佳方法是什么。使用资源文件或使用 WM_CREATE 消息的 CreateWindow 函数? 谢谢 最佳答案 我建议首先从对话框资源开始。然后,如果/当
采用以下代码: # pragma once // Windows specific files #include #include #include #include #include "IO
我是一名优秀的程序员,十分优秀!