【问题标题】:C++ WinAPI: HWND To String Returning HexC++ WinAPI:HWND 到字符串返回十六进制
【发布时间】:2016-11-07 23:30:28
【问题描述】:

我正在使用 WinAPI,我正在尝试制作一个允许您更改标题的程序。

#if defined(UNICODE) && !defined(_UNICODE)

#define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
#define UNICODE
#endif
#include <tchar.h>
#include <windows.h>

#include <string>
#include <sstream>

using namespace std;

string HWNDToString(HWND inputA);
void setTitle(string inputA);

LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
TCHAR szClassName[ ] = _T("CodeBlocksWindowsApp");
int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
{
    HWND hwnd;
    MSG messages;
    WNDCLASSEX wincl;

    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;
    wincl.style = CS_DBLCLKS;
    wincl.cbSize = sizeof (WNDCLASSEX);
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;
    wincl.cbClsExtra = 0;
    wincl.cbWndExtra = 0;
    wincl.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(255,128,0));

    if (!RegisterClassEx (&wincl)) return 0;

    hwnd = CreateWindowEx
    (
        0,
        szClassName,
        _T("Title Changer"),
        WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        400 + 22,
        400 + 49,
        HWND_DESKTOP,
        NULL,
        hThisInstance,
        NULL
    );

    ShowWindow (hwnd, nCmdShow);
    while (GetMessage (&messages, NULL, 0, 0))
    {
        TranslateMessage(&messages);
        DispatchMessage(&messages);
    }
    return messages.wParam;
}

HWND textout, titlebutton , powerbutton, textin;
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)                  /* handle the messages */
    {
        case WM_CREATE:
            textout = CreateWindow("STATIC", "Enter new window title here:", WS_VISIBLE | WS_CHILD | WS_BORDER, 0, 0, 230, 20, hwnd, NULL, NULL, NULL);
            textin = CreateWindow("EDIT", "New Title", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_AUTOHSCROLL, 0, 20, 250, 25, hwnd, (HMENU) NULL, NULL, NULL);
            titlebutton = CreateWindow("BUTTON", "Set as New Window Title", WS_VISIBLE | WS_CHILD | WS_BORDER, 0, 45, 210, 25, hwnd, (HMENU) /*=*/1/*=*/, NULL, NULL);
            powerbutton = CreateWindow("BUTTON", "Power Off", WS_VISIBLE | WS_CHILD | WS_BORDER, 316, 0, 100, 25, hwnd, (HMENU) 2, NULL, NULL);
        break;

        case WM_COMMAND:
            if (LOWORD(wParam) == 1)
            {
                SetWindowText(hwnd, HWNDToString(textin).c_str());
                MessageBox(hwnd, string("Title changed to: " + HWNDToString(textin)).c_str(), "Title Changed", MB_OK | MB_ICONINFORMATION);
            }

            if (LOWORD(wParam) == 2)
            {
                PostQuitMessage(0);
            }
        break;

        case WM_DESTROY:
            PostQuitMessage(0);
        break;

        default:
            return DefWindowProc (hwnd, message, wParam, lParam);
        break;
    }

    return 0;
}

string HWNDToString(HWND inputA)
{
    stringstream stringstreamBuffer;
    stringstreamBuffer << inputA;
    return stringstreamBuffer.str();
}

但程序将标题设置为随机的类似十六进制的字符串(例如,0x123abc)。

我定义的HWNDToString 函数有什么问题?我需要使用sprintf 将十六进制转换为字符串吗?

操作系统:Windows 7 Ultimate x64
IDE:代码块
编译器:GNU GCC 编译器(MinGW32)

【问题讨论】:

  • HWNDToString 将窗口句柄作为字符串返回给您。你期望它做什么?如果你想要窗口的标题,你需要使用GetWindowText()来阅读它。
  • @JonathanPotter 我正在尝试获取textin 的内容并将其转换为字符串。

标签: c++ string winapi converters hwnd


【解决方案1】:

HWND 是一个指针(struct HWND__*void*,分别取决于 STRICT 是启用还是禁用)。将这样的指针传递给基于std::ostream 的类的operator&lt;&lt; 将调用operator&lt;&lt;(const void*),它将指向的内存地址格式化为十六进制字符串。

由于您尝试使用EDIT 控件从用户接收字符串值,然后使用该字符串的值设置主窗口的标题,因此您应该使用GetWindowTextLength()GetWindowText() 函数来代替:

string HWNDToString(HWND inputA)
{
    string s;
    int len = GetWindowTextLength(inputA);
    if (len > 0)
    {
        s.resize(len + 1);
        len = GetWindowText(inputA, &s[0], s.size());
        s.resize(len);
    }
    return s;
}

case WM_COMMAND:
    if (LOWORD(wParam) == 1)
    {
        string s = HWNDToString(textin);
        SetWindowText(hwnd, s.c_str());
        MessageBox(hwnd, string("Title changed to: " + s).c_str(), "Title Changed", MB_OK | MB_ICONINFORMATION);
    }
    ...

附带说明,您的“关机”按钮应该向您的主窗口发送WM_CLOSE 消息,而不是直接调用PostQuitMessage()

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)                  /* handle the messages */
    {
        ...
        case WM_COMMAND:
            ....
            if (LOWORD(wParam) == 2)
            {
                SendMessage(hwnd, WM_CLOSE, 0, 0);
            }
            break;

        // By default, DefWindowProc() handles WM_CLOSE by destroying the window
        // using DestroyWindow(). WM_CLOSE is also received when the user closes
        // the window manually. This allows you to close down your app correctly
        // regardless of how the window is closed.  You can handle WM_CLOSE
        // manually if you want to prompt the user before allowing the
        // window to be destroyed...
        /*
        case WM_CLOSE:
            if (MessageBox(hwnd, "Are you sure you want to power down?", "Power Down?", MB_YESNO) == IDYES)
                DestroyWindow(hwnd);
            break;
        */

        case WM_DESTROY:
            PostQuitMessage(0);
            break;

        default:
            return DefWindowProc(hwnd, message, wParam, lParam);
    }

    return 0;
}

有关详细信息,请参阅 Destroying a Window 上的 MSDN 文档。

【讨论】:

  • 如果我要在其他地方使用 HWND 到字符串的转换,我希望能够做到这一点而无需阅读窗口标题。我现在使用DestroyWindow(hwnd) 作为电源关闭按钮,一切都立即关闭,谢谢。
  • @FluorescentGreen5 In case I were to use HWND to String conversion elsewhere, I would like do be able to do it without having to read the window title. 您发布的原始代码确实将 HWND 转换为字符串(表示其指针值)。但显然你的意思是EDIT 控件的内容,这就是上面答案中的GetWindowText 返回的内容。
  • @FluorescentGreen5 在EDIT 控件上调用GetWindowText() 会检索其内容,而不是其标题(它没有标题)。仅当您在具有标题的顶级窗口上调用 GetWindowText() 时,才会检索标题。这在GetWindowText() 文档中有明确说明:“将指定窗口标题栏(如果有)的文本复制到缓冲区中。如果指定窗口是控件,则复制控件的文本。 "
  • 我想我应该让自己更清楚。我希望代码将窗口标题设置为我在textin 文本框中指定的内容,并在消息框中显示textin 的内容,而不必依赖获取窗口标题的内容。为了解决我的问题,我需要做的就是弄清楚如何获取从HWNDToString 返回的十六进制字符串指向的数据。
  • 答案已经给你了,做你想做的事。
【解决方案2】:

对于那些偶然发现这个问题的人,这里有一个非常简单的功能:

#include <string>
#include <windows.h>

string HWNDToString(HWND input)
{
    string output = "";
    size_t sizeTBuffer = GetWindowTextLength(input) + 1;

    if(sizeTBuffer > 0)
    {
        output.resize(sizeTBuffer);
        sizeTBuffer = GetWindowText(input, &output[0], sizeTBuffer);
        output.resize(sizeTBuffer);
    }

    return output;
}

【讨论】:

    猜你喜欢
    • 2010-10-04
    • 2011-07-22
    • 1970-01-01
    • 2012-01-24
    • 1970-01-01
    • 1970-01-01
    • 2015-05-26
    • 2014-03-07
    • 1970-01-01
    相关资源
    最近更新 更多