Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Membre à l'essai
    [wxWidgets-3.1.1] [Code::Blocks 17.12] Utilisation de la fonction DC->Blit()
    Bonjour,

    J'ai suivi les vidéos

    Cet exercice permet de mettre en oeuvre les wxWidgets suivants : -wxFrame -wxMenuBar -wxDialog -wxButton -wxFileDialog -wxClientDC -wxMemoryDC -wxPanel -wxMenu -wxToolBar -wxBitmap -wxTheClipboard.

    J'ai refait tout le code en partant de zéro, mais j'ai un petit problème avec la fonction DC->Blit() et ses paramètres

    Voici le résultat que j'obtiens :


    La copie ne donne que le cadre du wxPanel qui est tout noir

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void MonPanelFrame::OnCopyClick(wxCommandEvent& event)
    {
        wxBitmap mon_bitmap_tmp(Panel1->GetSize(),wxBITMAP_SCREEN_DEPTH);
        mon_wxmemorydc->SelectObject(mon_bitmap_tmp);
        mon_wxmemorydc->Blit(wxPoint(0,0),Panel1->GetSize(),mon_wxclientdc,wxPoint(-1,-1),wxCOPY, true, wxDefaultPosition);
     
        if (wxTheClipboard->Open())
        {
            wxTheClipboard->SetData(new wxBitmapDataObject(mon_bitmap_tmp));
            wxTheClipboard->Close();
        }
    }


    Dans les liens de la vidéo en question, on trouve le source du projet et un exécutable.

    J'ai téléchargé le source puis je l'ai adapté à ma version, et cela donne le même résultat

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void My_ImageFrame::OnCopyClick(wxCommandEvent& event)
    {
        wxBitmap my_bitmap_tmp(Panel1->GetSize(),wxBITMAP_SCREEN_DEPTH);
        my_wxmemorydc->SelectObject(my_bitmap_tmp);
        my_wxmemorydc->Blit(wxPoint(0,0), Panel1->GetSize(), my_wxclientdc, wxPoint(-1,-1), wxCOPY, true, wxDefaultPosition);
     
        if (wxTheClipboard->Open())
            {
                 wxTheClipboard->SetData(new wxBitmapDataObject(my_bitmap_tmp));
                 wxTheClipboard->Close();
            }
    }


    Puis j'ai téléchargé l'exécutable qui lui fonctionne comme dans la vidéo


    Je cherche donc des précisions sur les 3 derniers paramètres de la fonction Blit()
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    bool wxDC::Blit 	( 	wxCoord  	xdest,
    		wxCoord  	ydest,
    		wxCoord  	width,
    		wxCoord  	height,
    		wxDC *  	source,
    		wxCoord  	xsrc,
    		wxCoord  	ysrc,
    		wxRasterOperationMode  	logicalFunc = wxCOPY,
    		bool  	useMask = false,
    		wxCoord  	xsrcMask = wxDefaultCoord,
    		wxCoord  	ysrcMask = wxDefaultCoord 
    	)


    Certains pourrons me répondre que je devrais poser ma question dans les commentaires de la vidéo, mais j'ai qq difficultés à poser une question compréhensible en grand-breton

    Ensuite, j'aurai une autre question, pour une second problème qui ne marche pas dans aucuns des 3 cas ci-dessus (donc aussi avec l'exécutable fourni), mais ce n'est peut être pas le sujet de l'exercice.
    Le wxPanel, n'est pas sauvegardé, donc si une autre fenêtre vient le recouvrir, quand la fenêtre revient en premier plan, le wxPanel est blanc

  2. #2
    Membre averti
    Salut.

    J'ai téléchargé les sources concernées, et j'ai failli avoir une syncope

    C'est une horreur ce code.
    Et je n'ose même pas penser à ce que ça donnerait si on le passait au détecteur de fuites mémoires.

    Bref : ce code fonctionne jusqu'à la version 3.0.x de wxWidgets.
    Mais pas avec la version 3.1.1 (comme il semblerait que c'est ce que tu utilises).

    En fait, quand tu utilises une classe dérivée de wxDC, il ne faut pas la stocker et l'utiliser tout au long de la durée de vie de l'application.

    Tu crées la variable quand tu en as besoin, et tu la détruis (ou tu fais en sorte qu'elle se détruise toute seule) quand tu n'en a plus besoin.
    D'ailleurs, c'est bien indiqué dans l'aide officielle, par exemple sur la page relative à wxClientDC

    Citation Envoyé par wxWidgets help
    Detailed Description
    A wxClientDC must be constructed if an application wishes to paint on the client area of a window from outside an EVT_PAINT() handler.

    This should normally be constructed as a temporary stack object; don't store a wxClientDC object.

    To draw on a window from within an EVT_PAINT() handler, construct a wxPaintDC object instead.

    To draw on the whole window including decorations, construct a wxWindowDC object (Windows only).

    A wxClientDC object is initialized to use the same font and colours as the window it is associated with.
    Donc la première code à faire dans le code téléchargé est de virer les lignes 114 et 116 du fichier "My_ImageMain.h" (celles relatives aux 2 wxDC).
    Ensuite tu vires les lignes 115 et 116 du fichier cpp correspondant (celles qui créent les 2 DC).
    Et après, chaque fois que ces variables étaient utilisées, tu adaptes le code en créant le(s) dc dont tu as besoin :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void My_ImageFrame::OnClearClick(wxCommandEvent& event)
    {
        wxClientDC dc(Panel1); // Pas de fuite mémoire car la variable est automatiquement supprimée
        dc.Clear();
    }

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    void My_ImageFrame::OnLoadClick(wxCommandEvent& event)
    {
        int dlg=FileDialog1->ShowModal();
            if(dlg==wxID_OK)
            {
                my_bitmap.LoadFile(FileDialog1->GetPath(),wxBITMAP_TYPE_ANY);
                wxClientDC dc(Panel1);
                dc.DrawBitmap(my_bitmap,0,0,false);
            }
    }
    void My_ImageFrame::OnDrawTextClick(wxCommandEvent& event)
    {
        wxClientDC dc(Panel1);
        dc.DrawText(wxT("wxWidgets logo"),100,200);
    }
     
    void My_ImageFrame::OnDrawCircleClick(wxCommandEvent& event)
    {
        wxClientDC dc(Panel1);
        dc.DrawCircle(20,20,10);
    }

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    void My_ImageFrame::OnCopyClick(wxCommandEvent& event)
    {
        wxBitmap my_bitmap_tmp(Panel1->GetSize(),wxBITMAP_SCREEN_DEPTH);
        wxMemoryDC mdc(my_bitmap_tmp);
     
        wxClientDC dc(Panel1);
        mdc.Blit(wxPoint(0,0),Panel1->GetSize(),&dc,wxPoint(-1,-1),wxCOPY,true,wxDefaultPosition);
        // il faut toujours désélectionner le bitmap avant de pouvoir l'utiliser
        mdc.SelectObject(wxNullBitmap);
     
            if (wxTheClipboard->Open())
                {
                    wxTheClipboard->SetData(new wxBitmapDataObject(my_bitmap_tmp));
                    wxTheClipboard->Close();
                }
    }


    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    void My_ImageFrame::OnSaveAsClick(wxCommandEvent& event)
    {
        wxBitmap my_bitmap_tmp(Panel1->GetSize(),wxBITMAP_SCREEN_DEPTH);
        wxMemoryDC mdc(my_bitmap_tmp);
        wxClientDC dc(Panel1);
        mdc.Blit(wxPoint(0,0),Panel1->GetSize(),&dc,wxPoint(-1,-1),wxCOPY,true,wxDefaultPosition);
        // Même remarque que précédemment
        mdc.SelectObject(wxNullBitmap);
     
            int dlg=FileDialog2->ShowModal();
            if(dlg==wxID_OK)
            {
                wxFileName my_file(FileDialog2->GetPath());
                wxString my_file_ext=my_file.GetExt().Lower();
     
                if(my_file_ext==wxT("xpm"))my_bitmap_tmp.SaveFile(FileDialog2->GetPath(),wxBITMAP_TYPE_XPM,NULL);
                else if(my_file_ext==wxT("jpeg"))my_bitmap_tmp.SaveFile(FileDialog2->GetPath(),wxBITMAP_TYPE_JPEG,NULL);
                else if(my_file_ext==wxT("bmp"))my_bitmap_tmp.SaveFile(FileDialog2->GetPath(),wxBITMAP_TYPE_BMP,NULL);
     
                else wxMessageBox(wxT("Extension ERROR"),wxT("ERROR"));
            }
    }


    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void My_ImageFrame::OnDrawRotatedTextClick(wxCommandEvent& event)
    {
        RotatedText tmp_dlg(this);
            int dlg=tmp_dlg.ShowModal();
            if(dlg==wxID_OK)
            {
                wxClientDC dc(Panel1);
                dc.DrawRotatedText(tmp_dlg.Text->GetValue(),tmp_dlg.X->GetValue(),tmp_dlg.Y->GetValue(),tmp_dlg.Angle->GetValue());
            }
    }


    Avec ces modifs, ça marche sans problème

    Et je n'ai pas regardé tout le code en détail, mais il y a d'autres trucs qui seraient à modifier dans le même style (par exemple les wxFileDialog).

    @+
    Xav'

  3. #3
    Membre à l'essai
    Bonsoir,

    Merci très bcp

    Citation Envoyé par wxXav Voir le message

    J'ai téléchargé les sources concernées, et j'ai failli avoir une syncope

    C'est une horreur ce code.
    Et je n'ose même pas penser à ce que ça donnerait si on le passait au détecteur de fuites mémoires.


    Citation Envoyé par wxXav Voir le message

    Avec ces modifs, ça marche sans problème

    Effectivement tout marche bien avec les modifs que tu m'as indiquées

    Merci encore.
    @+ Michel