创建的窗口没有标题

3

我正在从控制台应用程序中创建消息窗口。窗口类已正确注册并且窗口已正确创建,但它从未有过标题(尽管我的createwindow函数调用指定了一个标题)。 让我想到,控制台程序能否创建带名称的窗口?通过Google搜索,找不到任何有关信息。 以下是我的代码,保留了最少的内容:

using namespace std;
hInstance = GetModuleHandle(NULL);
WNDCLASS WndClass = {};
WndClass.style = CS_HREDRAW | CS_VREDRAW; // == 0x03
WndClass.lpfnWndProc = pWndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hIcon = 0;
WndClass.hCursor = 0;
WndClass.hbrBackground = (HBRUSH)COLOR_WINDOWFRAME;
WndClass.lpszMenuName = 0;
WndClass.lpszClassName = "EME.LauncherWnd";
int style = WS_OVERLAPPED | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU | WS_THICKFRAME | WS_CAPTION;
if (RegisterClassA(&WndClass))
{
    cout << "class registered. Hinstance : " << hInstance <<  " style : (expect 0xcf0000) " << std::hex << style << endl;
    HWND hwind2 = CreateWindowExA(0, "EME.LauncherWnd", "Mytitle", style, 0x80000000, 0x80000000, 0x80000000, 0x80000000, NULL, NULL, hInstance, NULL);
    if (hwind2 == 0)
        cout << "Couldn't create window" << endl;
    else
        cout << "created window" << endl;
}

输出:

class registered. Hinstance : 00E40000
created window

使用Nirsoft的Winlister进行检查,窗口存在,具有正确的类名("EME.LauncherWnd"),但没有名称。 此外,在代码块中添加以下几行:

if (0 == SetWindowText(hwind2, "aTitle"))
            cout << "couldn't set a title" << endl;
        else
            cout << "title set " << endl;

输出结果为

title set

然而,窗口仍然没有标题。如果控制台程序不能有标题,我会假设SetWindowText调用将返回0。

我做错了什么?

编辑:根据请求添加pWndProc。

LRESULT CALLBACK pWndProc(HWND hwnd,            // Handle to our main window
    UINT Msg,             // Our message that needs to be processed
    WPARAM wParam,        // Extra values of message 
    LPARAM lParam)        // Extra values of message
{
        switch (Msg)

        {
    case WM_DESTROY: 
....
break; 
         }
}

虽然在评论中提到pWndProc时,我认为它的主体与窗口的构建无关,但插入以下代码行作为switch case的默认值后,问题得以解决:
return DefWindowProc(hwnd, Msg, wParam, lParam);

解决问题。

2
“控制台程序能否创建带名称的窗口?”- 当然可以。毕竟,控制台本身只是一个普通的Win32应用程序。控制台应用程序完全可以访问Win32 API。话虽如此,pWndProc指向的确切内容是什么,并且它是否正确处理窗口消息呢? - Remy Lebeau
你需要一个消息循环。 - Cheers and hth. - Alf
投票关闭,因为缺乏可重现的示例。 - Cheers and hth. - Alf
3
你是否将所有未处理的消息传递给 DefWindowProc() 函数? - Jonathan Potter
显示剩余5条评论
1个回答

1
我将回答问题的答案发布在评论中建议的位置: 答案是,为了完成窗口创建,传递给RegisterClass WINAPI的pWndProc必须处理默认消息(特别是操作系统消息)。 在执行CreateWindow期间(在调用开始之后,在返回之前),pWndProc函数已经接收到它必须处理的消息,在我的情况下它没有处理这些消息。 这是一个标准的pWndProc函数:
LRESULT CALLBACK pWndProc(HWND hwnd,            // Handle to our main window
    UINT Msg,             // Our message that needs to be processed
    WPARAM wParam,        // Extra values of message 
    LPARAM lParam)        // Extra values of message
{
        switch (Msg)

        {
    case WM_DESTROY: 
...
    default:
        return DefWindowProc(hwnd, Msg, wParam, lParam);
         }
}

来源:

窗口过程通常不会忽略消息。如果它未处理消息,则必须将消息发送回系统进行默认处理。窗口过程通过调用DefWindowProc函数来执行此操作,该函数执行默认操作并返回消息结果。然后,窗口过程必须将此值作为其自己的消息结果返回。大多数窗口过程只处理几个消息,并通过调用DefWindowProc将其他消息传递给系统。


嗯,奇怪它居然能工作。不正常地处理WM_NCCREATE也会终止它。嗯,消息窗口是特殊的,可能就是这个原因。你不应该设置它们的文本,因为没有人能看到它,它们本来就是用来节省成本的。像Spy++这样的工具可以显示类名,完全足够了。 - Hans Passant
@HansPassant 尽管提问者谈到了消息窗口,但他没有传递 HWND_MESSAGE,因此这不是一个消息窗口。我认为他只是希望将其放在屏幕外,并希望不被注意到! - David Heffernan
我实际上是为了乐趣和知识收益(无利润)而进行程序逆向工程。我编写了自己的 MMORPG 启动器,其目的是在 5 秒内登录并启动游戏,而不是使用零售启动器需要 1 分钟的时间。我以与原始公司相同的方式创建了我的窗口(我调试了它们在 createwindow 和 registerclass 上的参数和函数调用),并且我使用了相同的标题/类名,这些名称不由我决定。 - user

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接