【问题标题】:WINAPI, old value in backround after RedrawWindow()WINAPI,RedrawWindow() 后背景中的旧值
【发布时间】:2020-12-31 23:32:28
【问题描述】:

我是 WINAPI 的初学者,想请教您的帮助。我有大约 10 个子窗口(编辑框)的主窗口。我需要点击其中 1 个并在另一个静态框中查看标签(文本)。问题是文本已更改,如您所见,先前操作的旧文本被绘制在背景中......

在重绘主窗口之前它仍然是透支的...... 我认为每次文本更改都重绘主窗口效率不高...... 有没有人有这个问题的经验? 你可以帮帮我吗? 非常感谢!

void vytvor_edit(HWND* h_edit,unsigned short ID)
{
    *h_edit = CreateWindowEx(WS_EX_CLIENTEDGE,
        WC_EDIT,
        NULL,
        WS_CHILD | WS_VISIBLE | ES_LEFT | ((ID_MINDISP != ID)?ES_NUMBER:0),
        0, 0, 200, 25,
        h_hlavni,
        (HMENU)ID,
        GetModuleHandle(NULL),
        NULL);
    if (*h_edit == NULL)
        FatalAppExit(0, L"nepovedlo se vytvorit ovladani");
    HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    SendMessage(*h_edit, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE);
    oldProc = (WNDPROC)SetWindowLongPtr(*h_edit,
        GWLP_WNDPROC, (LONG_PTR)WindowProcEdit);
}

void vytvor_combo(HWND* h_combo,unsigned short ID)
{
    *h_combo = CreateWindowEx(WS_EX_CLIENTEDGE,
        WC_COMBOBOX,
        NULL,
        WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS,
        0, 0, 200, 250,
        h_hlavni,
        (HMENU)ID,
        GetModuleHandle(NULL),
        NULL);
    if (*h_combo == NULL)
        FatalAppExit(0, L"nepovedlo se vytvorit ovladani");
    HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    SendMessage(*h_combo, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE);
    
    /*oldProc = (WNDPROC)SetWindowLongPtr(*h_edit,
        GWLP_WNDPROC, (LONG_PTR)WindowProcEdit);*/
}

void vytvor_button(HWND hwnd, HWND* h_button,const wchar_t* nazev,HMENU proces)
{
    *h_button = CreateWindowEx(WS_EX_CLIENTEDGE,
        WC_BUTTON,
        nazev,
        WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
        0, 0, 200, 50,
        hwnd,
        proces,
        GetModuleHandle(NULL),
        NULL);
    if (*h_button == NULL)
        FatalAppExit(0, L"nepovedlo se vytvorit ovladani");
    HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    SendMessage(*h_button, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE);

    /*oldProc = (WNDPROC)SetWindowLongPtr(*h_edit,
        GWLP_WNDPROC, (LONG_PTR)WindowProcEdit);*/
}

void vytvor_button_kalibrace(HWND hwnd, HWND* h_button, HMENU proces)
{
    *h_button = CreateWindowEx(WS_EX_CLIENTEDGE,
        WC_BUTTON,
        NULL,
        WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_OWNERDRAW,
        0, 0, 200, 200,
        hwnd,
        proces,
        GetModuleHandle(NULL),
        NULL);
    if (*h_button == NULL)
        FatalAppExit(0, L"nepovedlo se vytvorit ovladani");
    HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    SendMessage(*h_button, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE);

}

void vytvor_static(HWND* h_edit, unsigned short ID)
{
    *h_edit = CreateWindowEx(WS_EX_CLIENTEDGE,
        WC_STATIC,
        L"Info text",
        WS_CHILD | WS_VISIBLE | SS_SIMPLE,
        0, 0, 200, 25,
        h_hlavni,
        (HMENU)ID,
        GetModuleHandle(NULL),
        NULL);
    if (*h_edit == NULL)
        FatalAppExit(0, L"nepovedlo se vytvorit ovladani");
    HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    SendMessage(*h_edit, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE);
}

wm_paint

void wm_paint(HWND hwnd) noexcept
{
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hwnd, &ps);
    Gdiplus::Graphics* g = new Gdiplus::Graphics(hdc);
    RECT rect;
    GetClientRect(hwnd, &rect);
    
    g->DrawImage(pBitMapL, rect.right/12, 2, rect.right / 3 , rect.bottom - vyska_ovladani);
    g->DrawImage(pBitMapR, (rect.right*7)/12, 2, rect.right / 3, rect.bottom - vyska_ovladani); 
    if (pBitDisp != NULL)
    g->DrawImage(pBitDisp, rect.right / 2, rect.bottom - vyska_ovladani+4, rect.right / 2 - 4, vyska_ovladani-10);
    
    g->DrawImage(pBitDisp, rect.right / 2, rect.bottom - vyska_ovladani + 4, rect.right / 2 - 4, vyska_ovladani - 10);
    
    EndPaint(hwnd, &ps);
    delete g;
}

其他的

ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DISPARITYLADIC));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_DISPARITYLADIC);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassExW(&wcex);
}

//
//   FUNKCE: InitInstance(HINSTANCE, int)
//
//   ÚČEL: Uloží popisovač instance a vytvoří hlavní okno.
//
//   KOMENTÁŘE:
//
//        V této funkci uložíme popisovač instance do globální proměnné
//        a vytvoříme a zobrazíme hlavní okno programu.
//




BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // Uloží popisovač instance do naší globální proměnné.

   h_hlavni = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);


   if (!h_hlavni)
   {
      return FALSE;
   }

   vytvorit_ovladani();

   ShowWindow(h_hlavni, SW_MAXIMIZE);
 
  
   UpdateWindow(h_hlavni);

   return TRUE;
}

//
//  FUNKCE: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  ÚČEL: Zpracuje zprávy pro hlavní okno.
//
//  WM_COMMAND  - zpracování aplikační nabídky
//  WM_PAINT    - Vykreslení hlavního okna
//  WM_DESTROY  - vystavení zprávy o ukončení a návrat
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    
    switch (message)
    {
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // Analyzovat vybrané možnosti nabídky:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                SendMessage(hWnd, WM_CLOSE, 0, 0);
                break;
            case ID_SPOCITEJ:
            {
                SendMessage(hWnd, WM_PAINT, 0, 0);
                HANDLE h = (HANDLE)_beginthreadex(NULL, 0, vlakno_zpracovani, 0, NULL, NULL);
                CloseHandle(h);
            }
            break;
            case ID_NACTIKALIBRACI:
                nacti_kalibraci();
                break;

            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
    case WM_PAINT:
        {
            wm_paint(hWnd);         
        }
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    case WM_SIZE:
        posun_ovladani(hWnd);
        break;
    case WM_DRAWITEM:
        on_drawitem((DRAWITEMSTRUCT*)lParam);
        break;
    case WM_CLOSE:
        if (MessageBox(hWnd, L"probiha vypocet...chcete ukoncit?", L"Upozorneni", MB_YESNOCANCEL | MB_ICONQUESTION) == IDYES)
            return DefWindowProc(hWnd, message, wParam, lParam);
        else
            return 0;
        break;

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


LRESULT CALLBACK WindowProcEdit(HWND hWnd, UINT uMsg,
    WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_GETDLGCODE:
        return DLGC_WANTALLKEYS;
    
    case WM_SETFOCUS:
        unsigned int id =(unsigned int) GetMenu(hWnd);
        switch (id)
        {
        case ID_BLOCKSIZE:
        
            RECT rec;
            GetClientRect(h_static_infotext, &rec);
            BOOL ano;
            SetWindowText(h_static_infotext, L"BLOCK SIZE");
            RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE );
        
        
            break;
        case ID_DISPMAXDIFF:
            SetWindowText(h_static_infotext, L"DISPARITY ROZDIL");
            RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
            break;
        case ID_FILTERCAP:
            SetWindowText(h_static_infotext, L"FILTER CAP");
            RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
            break;
        case ID_MINDISP:
            SetWindowText(h_static_infotext, L"MIN DISPARITY");
            RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
            break;
        case ID_MODE:
            SetWindowText(h_static_infotext, L"MODE");
            RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
            break;
        case ID_NUMDISP:
            SetWindowText(h_static_infotext, L"HODNOTA DISPARITY");
            RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
            break;
        case ID_P1:
            SetWindowText(h_static_infotext, L"HODNOTA P1");
            RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
            break;
        case ID_P2:
            SetWindowText(h_static_infotext, L"HODNOTA P2");
            RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
            break;
        case ID_SPECKLERANGE:
            SetWindowText(h_static_infotext, L"SPECKLE ROZSAH");
            RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
            break;
        case ID_SPECKLESIZE:
            SetWindowText(h_static_infotext, L"SPECKLE VELIKOST");
            RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
            break;
        case ID_UNIQRATIO:
            SetWindowText(h_static_infotext, L"UNIQ RATIO");
            RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
            break;
        default:
            break;
        }
        
        break;
    }
    return CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam);
}

// Obslužná rutina zprávy pro pole O produktu
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

【问题讨论】:

  • 你没有展示你是如何创建h_static_infotext的。我的猜测是你使用了vytvor_static()。您正在使用 SS_SIMPLEthe documentation says “文本行不能以任何方式缩短或更改。”您正在更改文本并缩短它。

标签: c++ winapi


【解决方案1】:

问题是微软从未预料到静态控件中的文本会发生变化,因此他们没有实现适当的WM_ERASE 来擦除静态背景。您可以将控件子类化并自己完成,也可以在更改文本之前在静态控件上绘制背景颜色的矩形。

【讨论】:

  • 静态控件支持WM_ERASEBKGND(事实上,这就是我们有WM_CTLCOLORSTATIC的原因)。问题是 OP 使用了SS_SIMPLE 样式,它要求文本不能更改。
  • @RaymondChen 感谢您丢失的信息。我所知道的是,我过去在静态控制背景方面遇到过问题,这就是我追查到的原因。
猜你喜欢
  • 1970-01-01
  • 2014-04-29
  • 1970-01-01
  • 2017-05-08
  • 1970-01-01
  • 1970-01-01
  • 2022-11-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多