Avatar billede rafique Nybegynder
02. oktober 2003 - 16:30 Der er 9 kommentarer

Windows: dobbelt buffering i et vindue

Jeg har skrevet et program med MFC som, via GDI, tegner nogle rektangler (som skal forestille små vinduer) i et vindue, og lader brugeren trække rundt med dem på skærmen som om de var "rigtige" vinduer. Nydeligt.

Problemet er at det flimrer temmeligt meget når man trækker rundt med disse "vinduer". Specielt når der er mange af dem på skærmen på én gang. Jeg går ud fra dette skyldes at vinduet kun har én buffer...

Så derfor er mit spørgsmål:

Er det muligt at implementere dobbelt buffering i et vindue  uden at ty til et andet API som DirectX eller OpenGL, så man stadig kan tegne i det med GDI objekter?

Dette kan jo besvares blot med "ja" eller "nej", men jeg forbeholder mig retten til at give pointene til den første som kan forklare hvordan det gøres eller, hvis der argumeteres meget overbevisende, at det ikke kan lade sig gøre.
Avatar billede rafique Nybegynder
02. oktober 2003 - 16:32 #1
Jeg glemte vist at skrive på forhånd tak...
:-)
Avatar billede narrr Nybegynder
02. oktober 2003 - 16:39 #2
Kig på www.gametutorials.com -> Tutorials -> Win32
Avatar billede narrr Nybegynder
02. oktober 2003 - 16:40 #3
Avatar billede rafique Nybegynder
02. oktober 2003 - 17:03 #4
Tak for linket selvom om det er lidt pinligt at få sit åh så store problem besvaret med et link man selv burde have googlet sig frem til. Nå, men jeg skal lige bruge lidt tid til at forstå koden og overføre det til MFC før jeg kan acceptere - det bliver tidligst i aften måske først i morgen.
Avatar billede narrr Nybegynder
02. oktober 2003 - 19:02 #5
Jeg har selv brugt koden til at lave et lille snake spil med GDI.
Avatar billede rafique Nybegynder
10. oktober 2003 - 19:37 #6
Hej, du må sgu undskylde jeg ikke har givet lyd fra mig, jeg glemte det fuldstændigt efter jeg startede i skole her i mandags (weekenden inden var jeg fuld det meste af tiden...) Jeg har forsøgt at overføre principperne i eksemplet til mit MFC program, men der ikke nogen synlig forbedring. Her er noget af koden fra View-klassen der gerne skulle have dobbelt buffering:

Fra F00View.h

class CF00View : public CView {
private:
    (...)
    CRect m_clientRect;
    CDC m_backBufferDC;
    CBitmap m_backBufferBmp;
};

Fra F00View.cpp

void CInstrumentView::OnInitialUpdate(){
    (...)
    CDC *pDC = GetDC();
    GetClientRect(&m_clientRect);
    m_backBufferDC.CreateCompatibleDC(pDC);
    m_backBufferBmp.CreateCompatibleBitmap(pDC, m_clientRect.Width(), m_clientRect.Height());
    m_backBufferDC.SelectObject(&m_backBufferBmp);
}

void CInstrumentView::OnDraw(CDC* pDC){
    CBrush brush(RGB(255,255,255));
    m_backBufferDC.FillRect(m_clientRect,&brush); //tegn hvid baggrund

    [her tegner jeg nu en masse "vinduer" ved at give dem en pointer til min backbuffer, &m_backBufferDC]

    pDC->BitBlt(0, 0, m_clientRect.Width(), m_clientRect.Height(), &m_backBufferDC, 0, 0, SRCCOPY);
}
--SLUT--

Hvad gør jeg galt?
Avatar billede narrr Nybegynder
10. oktober 2003 - 19:56 #7
Det er efterhånen så lang tid siden jeg har rørt det double buffering stads at jeg overhovedet ikke kan huske det. Bare lige så du ikke sidder og venter på svar fra mig.
Avatar billede rafique Nybegynder
10. oktober 2003 - 20:02 #8
narr: OK. Jeg ville gerne give dig en del af pointene for linket, kan man det?
Avatar billede rafique Nybegynder
10. oktober 2003 - 20:43 #9
Mit forsøg på at lave et generelt kode eksempel går lidt i vasken når jeg begynder at blande CF00View og klassens egentlige navn, CInstrumentView sammen. Jeg har også ændret en anden lille uhensigtsmæssighed, så jeg prøver lige igen:

Fra F00View.h

class CF00View : public CView {
private:
    (...)
    CRect m_clientRect;
    CDC m_backBufferDC;
    CBitmap m_backBufferBmp;
    CBrush m_brush;
};

Fra F00View.cpp

void CF00View::OnInitialUpdate(){
    (...)
    CDC *pDC = GetDC();
    GetClientRect(&m_clientRect);
    m_backBufferDC.CreateCompatibleDC(pDC);
    m_backBufferBmp.CreateCompatibleBitmap(pDC, m_clientRect.Width(), m_clientRect.Height());
    m_backBufferDC.SelectObject(&m_backBufferBmp);
    m_brush.CreateSolidBrush(RGB(255,255,255));
}

void CF00View::OnDraw(CDC* pDC){
    m_backBufferDC.FillRect(m_clientRect,&m_brush); //tegn hvid baggrund

    [Her tegner jeg nu en masse "vinduer"...
    "Vinduerne" er objekter af en klasse
    med en paint(CDC *pDC) funktion, så de
    kan tegne sig selv når de får en pointer
    til et DC, i dette tilfælde &m_backBufferDC]

    pDC->BitBlt(0, 0, m_clientRect.Width(), m_clientRect.Height(), &m_backBufferDC, 0, 0, SRCCOPY);
}
//EOF
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester