Dialoge und die OnPaint-Methode...



  • Heyho,

    ich habe einen Dialog

    CPictureControlDlg::CPictureControlDlg(CWnd* pParent)
    	: CDialog(CPictureControlDlg::IDD, pParent)
    

    in diesem ist ein Picture Control enthalten. Mit der Methode

    void CPictureControlDlg::DrawSlidedImage(){...}
    

    zeichne ich dort ein Bild hinein. Dies muss ja immer beim neuzeichnen des Dialoges geschehen, also überschreibe ich die onPaint-Methode. Aber ich raffs irgendwie nicht.

    void CPictureControlDlg::OnPaint() 
    {
    	if (IsIconic())
    	{
    		CPaintDC dc(this); // device context for painting
    
    		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
    
    		// Center icon in client rectangle
    		int cxIcon = GetSystemMetrics(SM_CXICON);
    		int cyIcon = GetSystemMetrics(SM_CYICON);
    		CRect rect;
    		GetClientRect(&rect);
    		int x = (rect.Width() - cxIcon + 1) / 2;
    		int y = (rect.Height() - cyIcon + 1) / 2;
    
    		// Draw the icon
    		dc.DrawIcon(x, y, m_hIcon);
    		}
    	else{
                    CDialog::OnPaint();
                }
    
    	DrawSlidedImage();
    
    }
    

    mit dieser Variante wird das Bild bei der Initialisierung des Dialogs einmal kurz gezeichnet (blitzt auf) und dann wieder grau übermalt. Verschiebt man den Dialog, und erzwingt damit die OnPaint, wird es korrekt gezeichnet.

    else{
                    CDialog::OnPaint();
                    DrawSlidedImage();
                }
    

    und

    else{
                    DrawSlidedImage();
                    CDialog::OnPaint();
                }
    

    haben denselben Effekt.

    else
    	{
    		CDialog::OnPaint();
    		DrawSlidedImage();
    	}
    	DrawSlidedImage();
    

    hat zur Folge, dass das Bild gezeichnet wird, grau übermalt wird, und dann nochmal gezeichnet.
    Also der gewünschte Endeffekt, aber anscheinend nicht auf die feine Art! Das Bild wird dann ja in jeder onPaint dann zweimal gezeichnet.

    hier noch meine DrawSlidedImage-Funktion (das eigentlich Zeichnen findet in einer externen Klasse statt, ist denke ich unwichtig)

    void CPictureControlDlg::DrawSlidedImage(){
    
    	RECT picRect;
    	HDC pboxHDC = ::GetDC(m_pictureBox.m_hWnd);
    	m_pictureBox.GetWindowRect(&picRect);
    
    	m_pcfr->DrawImg(pboxHDC, picRect);
    
    	m_pictureBox.RedrawWindow(&picRect,NULL,RDW_UPDATENOW);
    
    	DeleteDC(pboxHDC);
    }
    

    kann mir jemand das Verhalten der onPaint() erklären?!



  • void CPictureControlDlg::OnPaint()
    {
        DrawSlidedImage();
    
    }
    


  • übergib DrawSlidedImage die CPaintDC Instanz. Rufe in DrawSlidedImage nicht GetDC auf.



  • und das m_pictureBox.RedrawWindow(&picRect,NULL,RDW_UPDATENOW); gehört meiner Meinung nicht in die OnPaint Methode.



  • wie komme ich da ran? (CPaintDC instanz)

    so sieht meine Zeichenmethode momentan aus...

    BOOL PicFrame::DrawImg(HDC hdc, RECT& rcBounds)
    {
        if (m_pImage)
        {
    
            Gdiplus::Graphics graphics(hdc);
    
            Gdiplus::Rect rc(0, 0, rcBounds.right - rcBounds.left, rcBounds.bottom - rcBounds.top);
    
    		REAL width = (REAL)rcBounds.right - (REAL)rcBounds.left;
    		REAL height = (REAL)rcBounds.bottom - (REAL)rcBounds.top;
    
    		Gdiplus::RectF destRect((REAL)0,(REAL)0,width, height), srcRect;
    		Gdiplus::Unit srcUnit;
    
    		m_pImage->GetBounds(&srcRect, &srcUnit );
    
    		// Bild Zentrieren
    		REAL xStart = destRect.Width/2 - srcRect.Width/2;
    		REAL yStart = destRect.Height/2 - srcRect.Height/2;
    		srcRect.X = srcRect.X + xStart;
    		srcRect.Y = srcRect.Y + yStart;
    
    		graphics.DrawImage(m_pImage, destRect, 0, 0, srcRect.Width, 
                                  srcRect.Height, srcUnit, NULL);
        }
    
    	DeleteDC(hdc);
        return TRUE;
    }
    


  • wenn ich CPaintDC, so wie ich bis jetzt gelesen habe, nur in der OnPaint Methode aufrufen kann (soll), dann nützt es mir nichts, da ich nicht nur Formen im Bild auf den Schirm sondern auch in den Speicher zeichnen will. So wie ich das verstehe, muss ich statt mit einem graphics Objekt dann mit dem CPaintDC Objekt zeichnen, oder nicht?

    Übrigens,

    else{
                    //CDialog::OnPaint();
                    DrawSlidedImage();
                }
    

    funktioniert zwar, macht das ganze beim verschieben aber extrem langsam im Bildaufbau!

    Eine Erklärung wäre nett...



  • Das RedrawWindow muss definitiv raus. Ein CPaintDC bekommt man mit CWnd::BeginPaint(). Dies erfordert auch ein EndPaint zu rufen. Beides ist zum Zeichnen meiner Ansicht nach dringend notwendig.

    Ein CPaintDC ist von CDC abgeleitet. Übergib also nur ein CDC und male in dieses. Wenn die Mal-Funktion aus OnPaint gerufen wird, übergibst Du das CPaintDC an statt eines CDC. Sollte ohne Probleme funktionieren.

    Gruß André


Anmelden zum Antworten