【问题标题】:win32: TextOut not being displayedwin32:TextOut 未显示
【发布时间】:2010-12-24 00:21:11
【问题描述】:

我最近让我的主窗口使用 WM_PAINT 编写文本,但现在我意识到这样做可能不是最好的消息,所以我正在尝试另一个版本;

主窗口包含一个菜单,在单击菜单项时会发送 ID_FILE_PID 消息,它会构建 4 个新窗口并在主窗口中显示文本(paintEditSigns 函数)。 4 个窗口工作正常,但文本根本不起作用,除非我在 main() 函数中这样做,如图所示......这到底是什么? O_O

顺便说一句:我仍然不知道为什么 StackOverflow 上的代码显示在我发布时总是看起来很奇怪,这是为什么呢?

switch(message)
   {
   case WM_COMMAND:
     switch (LOWORD(wParam))
       {
            case ID_FILE_PID:
            {
                HWND hWndButton;    
                HWND hWndEdit;
                HWND hWndEdit2;
                HWND hWndDisplay;

                // drawing the text in mainwindow
                trigger=true;

                // adding new windows in the mainwindow
                hWndButton = CreateWindowEx(0,TEXT("BUTTON"),"Modify",WS_CHILD | WS_VISIBLE |
                BS_DEFPUSHBUTTON, 170,56,80,30,hWnd,(HMENU)ID_BUTTON,hThisInstance,NULL);   
                hWndEdit = CreateWindowEx(0,RICHEDIT_CLASS,TEXT(""),WS_CHILD | WS_VISIBLE | WS_BORDER,
                120,30,80,25,hWnd,(HMENU)ID_EDIT,hThisInstance,NULL);
                hWndEdit2 = CreateWindowEx(0,RICHEDIT_CLASS,TEXT(""),WS_CHILD | WS_VISIBLE | WS_BORDER,
                220,30,80,25,hWnd,(HMENU)ID_EDIT2,hThisInstance,NULL);
                hWndDisplay = CreateWindowEx(0,TEXT("STATIC"),NULL,WS_CHILD | WS_VISIBLE | WS_BORDER,
                0,100,450,140,hWnd,(HMENU)ID_DISPLAY,hThisInstance,NULL);


                            UpdateWindow(hWnd);

                break;
            }

.....

case WM_PAINT:
     {
         if (trigger) {
             paintEditSigns()
         }
         break;

     }

//
// Main function
// 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
               LPSTR lpCmdLine, int nCmdShow)
{
    HWND hWnd;
    WNDCLASSEX wc;
    ZeroMemory(&wc, sizeof(WNDCLASSEX));
    hThisInstance = hInstance;
    LoadLibrary("Riched20.dll");

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszMenuName = MAKEINTRESOURCE(IDR_MYMENU);
    if(!(wc.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_MYICON)))) {
        HRESULT res = GetLastError();

    }
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
    wc.lpszClassName = TEXT("testcpp");
    RegisterClassEx(&wc);

    hWnd = CreateWindowEx(NULL, 
                            wc.lpszClassName,
                            TEXT("test"),
                            WS_OVERLAPPEDWINDOW,
                            300,
                            200,
                            450,
                            300,
                            NULL,
                            NULL,
                            hInstance,
                            NULL);
    ShowWindow(hWnd,nCmdShow);
        //paintEditSigns() -- here it works, but not when in the message part

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

    }


    return msg.wParam;
}



void paintEditSigns() {
    HFONT hf = createFont();
    PAINTSTRUCT ps;
    HWND hWnd = FindWindow(TEXT("testcpp"),TEXT("test"));
    HBRUSH hbruzh = CreateSolidBrush(RGB(0,0,0));
    HDC hdz = BeginPaint(hWnd,&ps); 
    string s = "Memory Address";

    SelectBrush(hdz,hbruzh);
    SelectFont(hdz,hf);
    TextOut(hdz,0,100,s.c_str(),s.length());
    EndPaint(hWnd,&ps);

    DeleteObject(hbruzh);   

}

HFONT createFont() {
    HDC hdc;
    long lfHeight;

    hdc = GetDC(NULL);
    lfHeight = -MulDiv(12, GetDeviceCaps(hdc, LOGPIXELSY), 72);
    ReleaseDC(NULL, hdc);

    HFONT hf = CreateFont(lfHeight, 0, 0, 0, 0, TRUE, 0, 0, 0, 0, 0, 0, 0, "MS Sans Serif");
    return hf;

}

【问题讨论】:

  • 要修复格式,您应该选择您的代码并单击编辑器工具栏中的{} 按钮,这会将所有代码缩进4个空格,然后stackoverflow会格式化为代码。
  • 关于您的代码的几个问题:1) 您不应该DeleteObject 在设备上下文中选择的 GDI 对象。通常的做法是保存旧的对象句柄,然后在DeleteObject 之前将其重新选择。 2) LoadLibrary 返回一个引用计数句柄。您应该在适当的时候释放该手柄。 3) 你不需要使用UpdateWindow。 GDI 和 winapi 绘画需要很多时间来适应,所以我想每个人都会在某些时候遇到这样的问题。仔细阅读 API 的 MSDN 文档,不要略读易混淆的部分;试着理解他们。

标签: c++ winapi textout


【解决方案1】:

您只能使用BeginPaint/EndPaint 来响应WM_PAINT。而WM_PAINT 就是这样画图的合适地方。

当窗口的一部分“无效”时,Windows 调用WM_PAINT。例如,如果您恢复窗口,或者在将窗口移开或调整窗口大小后部分窗口变得可见。

当您需要手动更新显示时,通过调用InvalidateRect“使需要重绘的区域无效”(这会告诉 Windows 需要重绘的窗口区域)。

常见的是只是使整个窗口无效,而不是计算您要绘制的区域的实际像素完美边界。

【讨论】:

  • 我对代码做了一点改动;单击菜单项时,布尔触发器设置为 true,然后我发送一条带有 WM_PAINT 的消息并执行 paintEditSigns(),但它仍然没有执行任何操作!
  • ...您不能直接发送 WM_PAINT。正如我所说 - 请仔细阅读 MSDN。正如我也说过的,使用InvalidateRect 来启动 WM_PAINT。
  • 是的,InvalidateRect 成功了,但我原以为它会被称为 UpdateWindow 的副作用>。
猜你喜欢
  • 2011-12-26
  • 1970-01-01
  • 2012-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-29
  • 2011-05-25
  • 1970-01-01
相关资源
最近更新 更多