как отключить сообщение WM_ONPAINT, которое будет получено моим окном в C ++ Builder? - PullRequest
0 голосов
/ 21 апреля 2011

Я рисую в другом потоке в моем окне, и когда моя форма получает WM_PAINT (или WM_ERASE ...), форма стирается, чтобы начать рисовать. Мне нужно помешать получению этого сообщения моим окном. Как это можно сделать?

Этот код просто рисует текущее время и день недели в виде строки в главной форме, когда получает сообщение WM_APP + 1.

void __fastcall TForm1::handleCustomMessage(TMessage &Message)
{

    static long id = 0;

    static DWORD sttick = 0;
    char tm[1024];
    DWORD curtick = GetTickCount()-sttick;
    SYSTEMTIME st;
    GetLocalTime(&st);
    static char sep[2] = ":";

    curtick = GetTickCount();
    if (curtick >= sttick+300)
    {
        sttick = curtick;
        sep[0] = (sep[0] == 0x20?':':0x20);
    }
    sprintf(tm, "%02d%s%02d%s%02d", st.wHour, sep, st.wMinute, sep, st.wSecond);
    // cnv->TextOutA(0, 0, tm);
    PAINTSTRUCT ps;
    // BeginPaint(hwnd,&ps);
    // if (!TextOutA(cnv->Handle, 0, 500, tm, strlen(tm)))
    // deb("textout: %s", fmterr());

    LOGFONT logFont;

    logFont.lfHeight = -(0.5 + 1.0 * Form1->Font->Size * 96 / 72);
    logFont.lfWidth = 0;
    logFont.lfEscapement = 0;
    logFont.lfOrientation = 0;
    logFont.lfWeight = Form1->Font->Style.Contains(fsBold) ? 700:400;
    logFont.lfItalic = Form1->Font->Style.Contains(fsItalic) ? TRUE:FALSE;
    logFont.lfUnderline = Form1->Font->Style.Contains(fsUnderline) ? TRUE:FALSE;
    logFont.lfStrikeOut = Form1->Font->Style.Contains(fsStrikeOut) ? TRUE:FALSE;
    logFont.lfCharSet = DEFAULT_CHARSET;
    logFont.lfOutPrecision = OUT_TT_PRECIS;
    logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
    logFont.lfQuality = NONANTIALIASED_QUALITY; // 1
    logFont.lfPitchAndFamily = FIXED_PITCH;
    char str[2035];
    strcpy(logFont.lfFaceName, deunicode(Form1->Font->Name.c_str(), str, sizeof(str)));
    HFONT hFont = NULL, hFontOld = NULL;
    hFont = CreateFontIndirect(&logFont);
    if (!hFont)
        deb("failed to create font: %s", fmterr());
    // HDC dc = GetWindowDC(Form1->Handle);
    hFontOld = (HFONT)SelectObject(Form1->pb->Canvas->Handle, hFont); // 2
    // Form1->Canvas->TextOut(0, 0, tm);
    //
    Form1->pb->Canvas->Font->Color = clWhite;
    Form1->pb->Canvas->Brush->Style = bsClear;
    // Form1->pb->Canvas->TextOutA(1,1,tm);
    // deb("out %s",tm);
    SetTextColor(Form1->pb->Canvas->Handle, clWhite);

    RECT rect;
    rect.left = 0;
    rect.right = Form1->pb->Width;
    rect.top = 1;
    rect.bottom = Form1->pb->Height;
    // FillRect(Form1->pb->Canvas->Handle,&rect, (HBRUSH) (COLOR_WINDOW+1));
    if(!TextOutA(Form1->pb->Canvas->Handle, 3,0,tm,strlen(tm)))
        deb("textout: %s",fmterr());
    //LockWindowUpdate(NULL);
    //int ret = DrawText(Form1->pb->Canvas->Handle, tm, strlen(tm), &rect, DT_CENTER|DT_NOCLIP|DT_EDITCONTROL);
    //if (!ret)
    //    deb("drawtext: %s", fmterr());
    // Form1->tedit->Text = tm;
    switch(st.wDayOfWeek)
    {
        case 1:
        strcpy(tm, "Понедельник");
        break;
        case 2:
        strcpy(tm, "Вторник");
        break;
        case 3:
        strcpy(tm, "Среда");
        break;
        case 4:
        strcpy(tm, "Четверг");
        break;
        case 5:
        strcpy(tm, "Пятница");
        break;
        case 6:
        strcpy(tm, "Суббота");
        break;
        case 7:
        strcpy(tm, "Воскресенье");
        break;
    }
    rect.top = Form1->Canvas->TextHeight(tm)+1;

    DeleteObject(hFont);
    logFont.lfHeight = -(0.5 + 1.0 * Form1->Font->Size * 96 / 90);
    logFont.lfWidth = 0;
    logFont.lfEscapement = 0;
    logFont.lfOrientation = 0;
    logFont.lfWeight = Form1->Font->Style.Contains(fsBold) ? 700:400;
    logFont.lfItalic = Form1->Font->Style.Contains(fsItalic) ? TRUE:FALSE;
    logFont.lfUnderline = Form1->Font->Style.Contains(fsUnderline) ? TRUE:FALSE;
    logFont.lfStrikeOut = Form1->Font->Style.Contains(fsStrikeOut) ? TRUE:FALSE;
    logFont.lfCharSet = DEFAULT_CHARSET;
    logFont.lfOutPrecision = OUT_TT_PRECIS;
    logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
    logFont.lfQuality = NONANTIALIASED_QUALITY; // 1
    logFont.lfPitchAndFamily = FIXED_PITCH;

    strcpy(logFont.lfFaceName, "tahoma");

    hFont = CreateFontIndirect(&logFont);
    if (!hFont)
        deb("failed to create font: %s", fmterr());
    // HDC dc = GetWindowDC(Form1->Handle);
    hFontOld = (HFONT)SelectObject(Form1->pb->Canvas->Handle, hFont);
    //if(!TextOutA(Form1->pb->Canvas->Handle, 0,Form1->Canvas->TextHeight(tm)+1,tm,strlen(tm)))
    //    deb("textout: %s",fmterr());
    int ret = DrawText(Form1->pb->Canvas->Handle, tm, strlen(tm), &rect, DT_CENTER|DT_NOCLIP|DT_EDITCONTROL);
    if (!ret)
        deb("drawtext: %s", fmterr());
    // Form1->dedit->Text = tm;
    // SelectObject(dc, hFontOld);
    // ReleaseDC(Form1->tedit->Handle,dc);
    DeleteObject(hFont);
    SelectObject(Form1->pb->Canvas->Handle, hFontOld);

Ответы [ 3 ]

0 голосов
/ 21 апреля 2011

Если у вас есть приложение WIn32, то где-то у вас будет похожий код: Ищите мои комментарии в коде.

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message)
    {
    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // Parse the menu selections:
        switch (wmId)
        {
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;
    case WM_ERASEBKGND: // NOT ONLY ON PAINT BUT EVEN HERE
    case WM_PAINT:
            // DO NOTHING
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

Я не знаю CBuilder, но все приложения Win32 имеют обработчик сообщений Windows. Вы должны найти, как это делается и где в вашей форме, поймать два сообщения и ничего не делать.

0 голосов
/ 26 апреля 2011

Игнорирование проблем безопасности потоков объекта canvas строителя C ++ ...

Вы всегда должны рисовать, используя правильный метод WM_PAINT. Хотя оконный менеджер в Windows 7 может рисовать вне BeginPaint / EndPaint, он вызывает низкопроизводительные пути кода, которые существуют исключительно для обратной совместимости.

Кроме того, существует ряд асинхронных событий, которые пользователь может инициировать (перемещая окна и т. Д.), Которые делают недействительной область окна, если окно не обновляется с помощью WM_PAINT, тогда будет видимая задержка, прежде чем окно будет перекрашены.

Менеджер окон рабочего стола (который реализует Aero Glass) действительно требует, чтобы вы использовали правильный способ перерисовки анимированного окна: используйте таймер, который вызывает InvalidateRect, чтобы сделать недействительной область с изменяющимся содержимым: и просто обработайте WM_PAINT для обработки перерисовки нового государства.

0 голосов
/ 21 апреля 2011

вы можете условно переопределить событие рисования чем-то вроде этого

<code>
protected virtual void OnPaint(PaintEventArgs e)
{
// Paint the control
// ...
// Raise the Paint event.
if (Paint != null)
Paint(this, e);
}

Конечно, это не код C ++, но идея в том, что в C Builder вы можете щелкнуть на вкладке событий формы, и должно быть событие onPaint, после того, как дважды щелкнувший по краске затем можно будет отключить. Я использую Delphi, а C ++ Builder - одна и та же компания, поэтому могут применяться одни и те же идеи. Но это не может быть решением ..

Обычно раздражающая вещь - это не столько перекрашивание, сколько перекраска фона, который в первую очередь вызывает мерцание. Вы можете включить использование двойной буферизации в форме, чтобы предотвратить некоторое мерцание. Или попробуйте перейти к событию erasebkgnd и просто обмануть окно, думая, что оно стерто.

<code>
private:
void __fastcall WMEraseBkgnd(TWMEraseBkgnd &Message);</p>

<p>void __fastcall TParentForm::WMEraseBkgnd(TWMEraseBkgnd& Message)
{
   Message.Result = true; // We didn't erase the background but we tell Windows we did
}
...