Copy/Pasting using wxClientDC wxMemoryDC produces black box in ms paint

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
User avatar
mjfmechanic
In need of some credit
In need of some credit
Posts: 3
Joined: Wed Jun 03, 2020 6:06 pm

Copy/Pasting using wxClientDC wxMemoryDC produces black box in ms paint

Post by mjfmechanic »

I have this line of code and I have repeatedly looked through the samples (dnd, clipboard, etc) to see if I'm perhaps missing something and I've tried most everything but the paste produces the same black box in ms paint. I've worked on this for a while, going on three weeks now prior to asking this question, so pretty embarrassed I can't figure it out, thanks for the help in advance.

The video I followed is: https://www.youtube.com/watch?v=42jJDAfFVfI

The excerpts I'm specifically working with are below. Everything else works fine. The code in question (in it's entirety) I've tried to attach using tar and zip and it states http error, if needed pls message me.

Code: Select all


void My_Image_wxFrame::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->AddData(new wxBitmapDataObject(my_bitmap_tmp));
                wxTheClipboard->Close();
            }
}


void My_Image_wxFrame::OnSaveAsClick(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);

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

PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Re: Copy/Pasting using wxClientDC wxMemoryDC produces black box in ms paint

Post by PB »

I took a look only at OnCopyClick(). I think you always need to unselect the bitmap from the memory DC once you are done drawing onto it, before doing anything else with it. E.g.:

Code: Select all

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

       // ADDED:
        my_wxmemorydc->SelectObject(wxNullBitmap);

        if (wxTheClipboard->Open())
            {
                wxTheClipboard->AddData(new wxBitmapDataObject(my_bitmap_tmp));
                wxTheClipboard->Close();
            }
BTW, do you really want to use (-1,-1) as the source origin?

BTW2, if you do not call wxTheClipboard->Flush(), the clipboard is going to be cleared when your application exits. Not sure if you really want it to work like this, at least on Windows such behaviour is not common.

EDIT
FWIW, here is a complete example that works for me on Windows 10 and stops working when I comment out the line selecting wxNullBitmap to
memoryDC.

Code: Select all

#include <wx/wx.h>
#include <wx/clipbrd.h>

class MyDialog : public wxDialog
{
public:
    MyDialog() : wxDialog(nullptr, wxID_ANY, "Test")
    {
        wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);

        mainSizer->Add(new wxButton(this, wxID_ANY, "Copy client area to Clipboard"),
            wxSizerFlags().Center().TripleBorder());
        Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MyDialog::OnCopyClientAreaToClipbard, this);

        SetSizerAndFit(mainSizer);
    }
private:
    void OnCopyClientAreaToClipbard(wxCommandEvent&)
    {
        const wxSize clientSize = GetClientSize();

        wxBitmap   bitmap(clientSize, wxBITMAP_SCREEN_DEPTH);
        wxMemoryDC memoryDC(bitmap);
        wxClientDC clientDC(this);

        memoryDC.Blit(wxPoint(0,0), clientSize, &clientDC, wxPoint(0,0));
        memoryDC.SelectObject(wxNullBitmap);

        if ( wxTheClipboard->Open() )
        {
            wxTheClipboard->SetData(new wxBitmapDataObject(bitmap));
            wxTheClipboard->Close();
            wxTheClipboard->Flush();
        }
    }
};

class MyApp : public wxApp
{
public:
    bool OnInit() override
    {
        (MyDialog()).ShowModal();
        return false;
    }
}; wxIMPLEMENT_APP(MyApp);
User avatar
mjfmechanic
In need of some credit
In need of some credit
Posts: 3
Joined: Wed Jun 03, 2020 6:06 pm

Re: Copy/Pasting using wxClientDC wxMemoryDC produces black box in ms paint

Post by mjfmechanic »

@pb WOW that was easy...I'm not sure where I missed that SelectObject(wxNullBitmap) in my searching/reading, bewildering but of course it works.

About the xsrc, ysrc, it was how the guy coded it in the video. Is there a reason he used that instead of (0,0)?

The Thanks for the quick reply!
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Re: Copy/Pasting using wxClientDC wxMemoryDC produces black box in ms paint

Post by PB »

I am not familiar with that video, so I do not know why (-1,-1) was used. As far as I can tell, using -1 there does not have any special meaning and is considered an actual coordinate.
Post Reply