hvordan deaktiveres WM\_ONPAINT-besked, der skal modtages af mit vindue i C ++ Builder?

Indlæg af Hanne Mølgaard Plasc

Problem



jeg 'laver maleri i en anden tråd i mit vindue, og når min formular modtager WM\_PAINT (eller WM\_ERASE ...) formularen slettes for at begynde at male. Jeg skal stoppe denne besked fra at modtage ved mit vindue. Hvordan kan dette opnås?


Denne kode måler bare den aktuelle tid og ugedag i strengtype på hovedformularen, når den modtager WM\_APP + 1 besked.


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);

Bedste reference


Hvis du antager, at du har en WIn32-applikation, så vil du have et lignende kode:
Se efter mine kommentarer i koden.


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;
}


Jeg kender ikke CBuilder, men Win32 apps har alle en Window Message Handler. Du skal finde ud af, hvordan det er gjort, og hvor i din form og fange disse to meddelelser og ikke gøre noget.

Andre referencer 1


Ignorerer trådsikkerhedsproblemerne i C ++ builderens lærredsobjekt ...


Du bør altid gøre dit maleri fra den rigtige WM\_PAINT-metode. Mens vinduesbehandleren på Windows 7 kan tegne uden for BeginPaint/EndPaint, påberåber den lave præstations kodeveje, der udelukkende eksisterer for bagudkompatibilitet.


Der er også en række asynkronhændelser, som brugeren kan udløse (ved at flytte vinduer osv.), Der ugyldiggør et område i et vindue, hvis vinduet ikke opdateres af WM\_PAINT, så vil der være en synlig latens, før vinduet bliver malet.


Desktop Window Manager (der implementerer Aero Glass) kræver virkelig, at du bruger den rigtige måde at genrave et animeret vindue: Brug en timer, der kalder InvalidateRect for at ugyldiggøre området med det ændrede indhold: Og håndter blot WM\_PAINT for at håndtere omsmalningen af ​​den nye stat.

Andre referencer 2


du kan tilsidesætte malingsbegivenheden betinget med noget som dette



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



givet dette er ikke c ++ kode, men ideen er, at i C builder kan du klikke på fanen begivenheder i formularen og der skal være en begivenhed kaldet onPaint, så kan dobbeltklækket maling derefter deaktiveres. Jeg bruger Delphi og C ++ Builder er samme firma, så de samme ideer kan gælde. Men det er måske ikke løsningen ..


Generelt er den irriterende ting med dette ikke gentemper så meget som baggrunden af ​​baggrunden, som får flimmer i første omgang. Du kan muliggøre brug af dobbeltbuffering på formularen for at forhindre, at nogle flimrer dog. Eller prøv at gå til den erasebkgnd begivenhed og bare narre vinduer til at tro, det er blevet slettet.



private:
void \_\_fastcall WMEraseBkgnd(TWMEraseBkgnd &Message);

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