【问题标题】:Windows API: How to Draw Text to Child Window? [duplicate]Windows API:如何将文本绘制到子窗口? [复制]
【发布时间】:2016-05-15 09:39:46
【问题描述】:

我最近开始学习 windows API 并希望制作更多交互式 GUI 应用程序。所有代码都是用 C++ 编写的。

我所做的是制作了一个自定义按钮窗口,而不是使用内置按钮类。我希望每个按钮都有不同的文本,并希望在父窗口中进行设置。

所以我创建了按钮并保存了句柄:

hNavBtnNews = CreateWindow(szUW_NAV_BTN, "News", WS_CHILD | WS_VISIBLE, 540, 0, 100, HEADER_HEIGHT, header, NULL, NULL, NULL);

然后为了确保这没有失败,我检查了句柄并尝试绘制文本:

                if(hNavBtnNews == NULL){
                    printf("\nFailed to Create Window Nav Button \n");
                }else{
                    printf("\nCreated Window Nav Button");
                    HDC hdc;
                    PAINTSTRUCT ps;
                    RECT rect;
                    hdc = BeginPaint(hNavBtnNews, &ps);
                    SetBkMode(hdc, TRANSPARENT);
                    SetTextColor(hdc, BG_TXT_COLOR);
                    GetClientRect(hNavBtnNews, &rect);
                    DrawText(hdc, "News", -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
                    EndPaint(hNavBtnNews, &ps);
                }

这都是在父窗口过程的 WM_CREATE 情况下完成的(它本身工作得很好)。文本为浅灰色,按钮的背景为深蓝色。除了没有绘制文本。也没有编译器警告或错误。也许对内置控件进行子类化会更好,尽管我不知道如何。对于解决此问题的任何帮助将不胜感激。

【问题讨论】:

  • BeginPaint: “应用程序不应调用 BeginPaint,除非是响应 WM_PAINT 消息。”
  • 您始终可以在标准按钮上使用SetWindowSubclass,然后只需处理 WM_PAINT 消息并在那里进行绘图 - 不是在主窗口的 WindowProc 中。
  • 您不能只绘制一次窗口,然后期望它永远可见。每当操作系统告诉您需要绘制窗口时,您都必须进行绘制。
  • 您正在将像素喷溅到尚不可见的窗口中。直到您调用 ShowWindow() 之后才会发生这种情况。这些像素不会长期存在,当窗口自己绘制时会再次透支。这需要多长时间是完全无法预测的。只是不要这样做。
  • 当然,您可以在 WM_PAINT 处理程序之外进行绘制。但这不是系统设计的工作方式。每当需要绘制窗口的一部分时,系统都会发送WM_PAINT 消息。如果您不处理该消息,那么您在 WM_PAINT 处理程序之外绘制的任何内容都将丢失。

标签: c++ windows winapi


【解决方案1】:

考虑以下简短的 sn-p 作为一个简单的子类化示例:

LRESULT CALLBACK myDrawButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam,
                                     LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    switch (uMsg)
    {
        case WM_PAINT:
            onBtnPaint(hWnd, wParam, lParam);
            return TRUE;
    }
    return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}

BOOL CALLBACK DlgMain(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
    case WM_INITDIALOG:
    {
        HWND button = GetDlgItem(hwndDlg, IDC_BUTTON_TO_SUBCLASS);
        SetWindowSubclass(button, myDrawButtonProc, 0, 0);
    }
    return TRUE;
...
...
...

【讨论】:

  • 您忘记删除子类化。我认为您可以在子类过程中添加 WM_NCDESTROY 处理程序,然后将其删除... +1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-05
  • 1970-01-01
  • 1970-01-01
  • 2017-06-21
  • 2013-08-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多