如何转换旧的C++剪贴板程序?

问题描述 投票:0回答:0

我正在改造一些早期的基于MFC的代码。其中有当时运行良好的剪贴板例程。但是当我用 Visual Studio 2022 重建它们时,它们构建但在程序运行时挂在

EmptyClipboard()
。有时当我单步执行代码时,它会起作用,但大多数时候它会在同一点挂起,并给出“断点指令(
__debugbreak()
语句或类似调用)已执行”消息作为唯一的解释。如果程序在调试之外运行,那么它就会终止。微软的文献表明
OpenClipboard()
调用了
HWND
NULL
的参数,但是如果使用了
NULL
那么
SetClipboardData
过程将会失败。该计划似乎没有那么远。
OpenClipboard()
的旧版本不需要任何参数,如果我尝试输入一个,它会被拒绝。文献要求 winuser.h 的头文件。但在#included 之后,没有区别,
OpenClipboard()
仍然不带参数。有没有人知道发生了什么事?谢谢。

这是整个原工作函数;

void CDibView::OnEditCopy()
{   
    if( m_id == ID_PALETTEEDIT )
    {
        m_edit.Copy();
        return;
    }
    BeginWaitCursor();
    CDibDoc* pDoc = GetDocument();
    // Clean clipboard of contents, and copy the DIB.

    if (OpenClipboard())
    {   
        BITMAPINFOHEADER    m_Dibhead;
        HANDLE  m_hBitstore2;
        
        m_Dibhead.biSize = sizeof (BITMAPINFOHEADER);
        
        CSize now = rectSave.Size();
        
        m_Dibhead.biWidth = now.cx;
        m_Dibhead.biHeight = now.cy;
        m_Dibhead.biPlanes = 1;
        m_Dibhead.biBitCount = 24;
        m_Dibhead.biCompression = 0;
        m_Dibhead.biSizeImage = ((DWORD)m_Dibhead.biWidth * m_Dibhead.biBitCount/ 8) * (DWORD)m_Dibhead.biHeight;
        m_Dibhead.biXPelsPerMeter = 0;
        m_Dibhead.biYPelsPerMeter = 0;
        m_Dibhead.biClrUsed = 0;
        m_Dibhead.biClrImportant = 0;
        
        DWORD count = (((DWORD)m_Dibhead.biWidth * m_Dibhead.biBitCount/ 8) * (DWORD)m_Dibhead.biHeight) + (unsigned long)sizeof( BITMAPINFOHEADER );
        HBITMAP hBitmap2;
        char huge* m_pBitstore;
        LPBITMAPINFOHEADER binfo;
        CClientDC dc( this );
        int next;
        for( next = 0; next < 2000; next++ )
        {
             m_pBitstore = (char huge*)GlobalAllocPtr( GPTR, count + (unsigned long)next );
             binfo = (LPBITMAPINFOHEADER)m_pBitstore;
             *binfo = m_Dibhead;
             if( !(hBitmap2 = ::CreateDIBitmap( dc.m_hDC, (LPBITMAPINFOHEADER)m_pBitstore, CBM_INIT, (LPSTR)m_pBitstore + (unsigned long)sizeof( BITMAPINFOHEADER ), (LPBITMAPINFO)m_pBitstore, DIB_RGB_COLORS ) ))
             {
                GlobalFreePtr( m_pBitstore );    //There is a problem in fabricating the packed DIB used by clipboard here
             }                                   //which dosn't seem to show until an attempt to construct a devise dependant
             else                                //bitmap used in the data transfer.  This loop searches for a size of memory
                break;                           //allocation which will function.
        }
        GlobalFreePtr( m_pBitstore );
/*
        #ifdef _DEBUG
            afxDump << "Dumping next: =  "
                    <<  next
                    << "\n";
        #endif
 */
        m_hBitstore2 = (HANDLE) ::GlobalAlloc( GPTR, count + (unsigned long)next );
        LPBITMAPINFOHEADER m_pBitstore2;
        m_pBitstore2 = (LPBITMAPINFOHEADER) ::GlobalLock( (HGLOBAL) m_hBitstore2 );
        *m_pBitstore2 = m_Dibhead;
        ::GlobalUnlock((HGLOBAL) m_hBitstore2);
        m_pBitstore = (char huge*) ::GlobalLock((HGLOBAL) m_hBitstore2);
        
        CDibDoc* pDoc = GetDocument();
        HDIB hDIB = pDoc->GetHDIB();
        BYTE huge *    lpDIBHdr;            // Pointer to BITMAPINFOHEADER
        BYTE huge *    lpDIBBits;           // Pointer to DIB bits
        lpDIBHdr  = (BYTE huge *) ::GlobalLock((HGLOBAL) hDIB);
        lpDIBBits = (BYTE huge *)::FindDIBBits((LPSTR)lpDIBHdr);
        HDC hdcMem;
        HDC hdcMem2;
        hdcMem = ::CreateCompatibleDC( dc.m_hDC );//create a memory device context (display surface)
        hdcMem2 = ::CreateCompatibleDC( dc.m_hDC );     
        HBITMAP hBitmap;
        hBitmap = CreateDIBitmap( dc.m_hDC, (LPBITMAPINFOHEADER)lpDIBHdr, CBM_INIT, lpDIBBits, (LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS );
        char huge* ptr;
        ptr = m_pBitstore + (unsigned long)sizeof (BITMAPINFOHEADER);
        LPBITMAPINFOHEADER info;
        info = (LPBITMAPINFOHEADER)m_pBitstore;
        LPBITMAPINFO info2;
        info2 = (LPBITMAPINFO)m_pBitstore;      
        hBitmap2 = ::CreateDIBitmap( dc.m_hDC, info, CBM_INIT, ptr, info2, DIB_RGB_COLORS );
        ::SelectObject( hdcMem, hBitmap );//make this local bitmap the display surface
        ::SetMapMode( hdcMem, MM_TEXT );
        ::SelectObject( hdcMem2, hBitmap2 );//make this local bitmap the display surface            
        ::SetMapMode( hdcMem2, MM_TEXT );
        CPoint cp, pc;
        cp.x = rectSave.left;
        cp.y = rectSave.top;
        pc = DibPoint( cp );                
        ::BitBlt( hdcMem2, 0, 0,(int)m_Dibhead.biWidth,(int)m_Dibhead.biHeight, hdcMem, pc.x, pc.y, SRCCOPY );          
        ::GetDIBits( dc.m_hDC, hBitmap2, 0, (int)m_Dibhead.biHeight, ptr, info2, DIB_RGB_COLORS );
        if( m_bIscut )    //If Cut does this.
        {  
            LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB
            lpbmi = (LPBITMAPINFOHEADER)lpDIBHdr;
            ::PatBlt( hdcMem, pc.x, pc.y, (int)m_Dibhead.biWidth, (int)m_Dibhead.biHeight, WHITENESS );//clear contend of local bitmap
            ::GetDIBits( dc.m_hDC, hBitmap, 0, (int)lpbmi->biHeight, lpDIBBits,(LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS );
            pDoc->SetModifiedFlag(TRUE);
            m_bIscut = FALSE;
            ::InvalidateRect( this->m_hWnd, NULL, FALSE );
        }                               
/*      
        #ifdef _DEBUG
            afxDump << "Dumping m_hBitstore2: =  "
                    <<  m_hBitstore2
                    << "\n";
        #endif
*/          
        ::GlobalUnlock((HGLOBAL) m_hBitstore2);
        
        EmptyClipboard();
        SetClipboardData (CF_DIB, CopyHandle((HANDLE)m_hBitstore2));
        CloseClipboard();
        
        
        ::GlobalFree((HGLOBAL) m_hBitstore2);
        ::DeleteDC( hdcMem );
        ::DeleteObject( hBitmap );      
        ::GlobalUnlock((HGLOBAL) hDIB);
        ::DeleteDC( hdcMem2 );
        ::DeleteObject( hBitmap2 );     
        EndWaitCursor();
    }
}

#define huge /* nothing */
取消巨大的关键字。

从上面的初始查询开始,我推断问题出在程序挂起之前,但没有说明原因。翻遍文献后,我还没有找到解决办法。该程序基于旧的 Biblook 示例。当时的例程,用于复制,是从其他地方复制的,用于在客户区中操作区域的代码,仍然可以正常工作。复制和粘贴的代码在当时也是有效的。 如果我将 ptr 变量从原来的更改为如下所示,那么复制和粘贴过程在第一次访问时可以正常工作,但不会再有。如果我取消

::GetDIBits(dc.m_hDC, hBitmap2, 0, (int)m_Dibhead.biHeight, ptr, info2, DIB_RGB_COLORS);
程序那么程序不会挂断但它不会复制选定的客户区。

下面是带有注释的函数的当前状态,因为我试图确定该函数。在这一点上,我假设目前采用了一个完全不同的过程,但我找不到它的例子。或者我的代码中仍然存在我无法确定的错误。

 void CDibView::OnEditCopy()
{   
    if( m_id == ID_PALETTEEDIT ) //Do this if copying text
    {
        m_edit.Copy();
        return;
    }
    BeginWaitCursor();
    CDibDoc* pDoc = GetDocument();
    // Clean clipboard of contents, and copy the DIB.
    //COleDataSource* pData = new COleDataSource; //For test
    if (::OpenClipboard(m_hWnd))
    {
        //* Setup Dib header
        //With #include <wingdi.h>
        BITMAPINFOHEADER    m_Dibhead;//Header
        BITMAPV5HEADER      m_V5Dibhead;//Tested but ::CreateDIBitmap wouldn't take
        HANDLE  m_hBitstore2;
            //*Fill header fields
        m_Dibhead.biSize = sizeof(BITMAPINFOHEADER);
        m_V5Dibhead.bV5Size = sizeof(BITMAPV5HEADER);

        CSize now = rectSave.Size(); //Size of select rectangle

        m_Dibhead.biWidth = now.cx;
        m_V5Dibhead.bV5Width = now.cx;
        m_Dibhead.biHeight = now.cy;
        m_V5Dibhead.bV5Height = now.cy;
        m_Dibhead.biPlanes = 1;
        m_V5Dibhead.bV5Planes = 1;
        m_Dibhead.biBitCount = 24;
        m_V5Dibhead.bV5BitCount = 24;
        m_Dibhead.biCompression = 0;
        m_V5Dibhead.bV5Compression = 0;
        m_Dibhead.biSizeImage = ((DWORD)m_Dibhead.biWidth * m_Dibhead.biBitCount / 8) * (DWORD)m_Dibhead.biHeight;
        m_V5Dibhead.bV5SizeImage = m_Dibhead.biSizeImage;
        m_Dibhead.biXPelsPerMeter = 0;
        m_V5Dibhead.bV5XPelsPerMeter = 0;
        m_Dibhead.biYPelsPerMeter = 0;
        m_V5Dibhead.bV5YPelsPerMeter = 0;
        m_Dibhead.biClrUsed = 0;
        m_V5Dibhead.bV5ClrUsed = 0;
        m_Dibhead.biClrImportant = 0;
        m_V5Dibhead.bV5ClrImportant = 0;
        //* End header setup
            //Size of Dib file in DWORD
        DWORD count = (((DWORD)m_Dibhead.biWidth * m_Dibhead.biBitCount / 8) * (DWORD)m_Dibhead.biHeight) + (unsigned long)sizeof(BITMAPINFOHEADER);
        //DWORD count = (((DWORD)m_Dibhead.biWidth * m_Dibhead.biBitCount / 8) * (DWORD)m_Dibhead.biHeight) + (unsigned long)sizeof(BITMAPINFOHEADER);
        HBITMAP hBitmap2;   //Bitmap handle for Clipboard
        char* m_pBitstore;  //Character pointer to Dib data
        
        CClientDC dc(this);

        //Below was used with early memory architecture to find the smallest usable memory for needed dib
            //* Find smallest memory storage that CreateDIBitmap will take
        int next = 0;
        //for (next = 0; next < 2000; next++)
        //{     // Establish a memory size to test
        //  m_pBitstore = (char*)GlobalAllocPtr(GPTR, count + (unsigned long)next);
        //      //Test it
        //  if (!(hBitmap2 = ::CreateDIBitmap(dc.m_hDC, (LPBITMAPINFOHEADER)m_pBitstore, CBM_INIT, (LPSTR)m_pBitstore + (unsigned long)sizeof(BITMAPINFOHEADER), (LPBITMAPINFO)m_pBitstore, DIB_RGB_COLORS)))
        //  {
        //      GlobalFreePtr(m_pBitstore);    //There is a problem in fabricating the packed DIB used by clipboard here
        //  }                                   //which dosn't seem to show until an attempt to construct a devise dependant
        //  else                                //bitmap used in the data transfer.  This loop searches for a size of memory
        //      break;                           //allocation which will function.
        //}
        //GlobalFreePtr(m_pBitstore); // Free up this memory
        //::DeleteObject(hBitmap2); //Delete the test dib
        
            // Establish memory for dib using the above tested size
        // was m_hBitstore2 = (HANDLE) ::GlobalAlloc( GPTR, count + (unsigned long)next );
        m_hBitstore2 = (HANDLE) ::GlobalAlloc(GMEM_FIXED, count + (unsigned long)next);
        LPBITMAPINFOHEADER m_pBitstore2; // Establish pointer to this memory and thus the header
        m_pBitstore2 = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL)m_hBitstore2);
        *m_pBitstore2 = m_Dibhead; // Copy the header values to memory
            // Unlock the memory for the dib and then relock to retrieve a char pointer
        ::GlobalUnlock((HGLOBAL)m_hBitstore2);
        m_pBitstore = (char*) ::GlobalLock((HGLOBAL)m_hBitstore2);
            //* Get a handle to the whole client window
        HDIB hDIB = pDoc->GetHDIB();
        BYTE* lpDIBHdr;            // Pointer to BITMAPINFOHEADER
        BYTE* lpDIBBits;           // Pointer to DIB bits
        lpDIBHdr = (BYTE*) ::GlobalLock((HGLOBAL)hDIB);
        lpDIBBits = (BYTE*)::FindDIBBits((LPSTR)lpDIBHdr);
            // Make two device contexts
        HDC hdcMem; // One for cutting out the selection box content
        HDC hdcMem2; // One for placing into Clipboard
        hdcMem = ::CreateCompatibleDC(dc.m_hDC);//create a memory device context (display surface)
        hdcMem2 = ::CreateCompatibleDC(dc.m_hDC);
            // Create new bitmap using the hDib content
        HBITMAP hBitmap;
        hBitmap = ::CreateDIBitmap(dc.m_hDC, (LPBITMAPINFOHEADER)lpDIBHdr, CBM_INIT, lpDIBBits, (LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS);
            // Make pointer to the dib data
        char* ptr;
        //ptr = m_pBitstore + (unsigned long)sizeof(BITMAPINFOHEADER);
        ptr = m_pBitstore + (lpDIBBits - lpDIBHdr);
            // Make poiner to header in the established memory
        LPBITMAPINFOHEADER info;
        info = (LPBITMAPINFOHEADER)m_pBitstore;
            // Make  pointer to a BITMAPINFOHEADER struct plus a RGBQUAD struct
        LPBITMAPINFO info2;
        info2 = (LPBITMAPINFO)m_pBitstore;
            // Create the new (BUT EMPTY) dib using these values
        hBitmap2 = ::CreateDIBitmap(dc.m_hDC, info, CBM_INIT, ptr, info2, DIB_RGB_COLORS);
        ::SelectObject(hdcMem, hBitmap);//make this local bitmap for cutting out selection box
        ::SetMapMode(hdcMem, MM_TEXT);
        ::SelectObject(hdcMem2, hBitmap2);//make this local bitmap for the Clipboard            
        ::SetMapMode(hdcMem2, MM_TEXT);
            // Retrieve location for top-left corner of selection box
        CPoint cp, pc;
        cp.x = rectSave.left;
        cp.y = rectSave.top;
        pc = DibPoint(cp); // Find location of data in client window
            // Retrieve color data from selection box for Clipboard and put it in new dib
        BOOL bb = ::BitBlt(hdcMem2, 0, 0, (int)m_Dibhead.biWidth, (int)m_Dibhead.biHeight, hdcMem, pc.x, pc.y, SRCCOPY);
        if (!bb)
        {
            ::MessageBox(m_hWnd, "BitBlt has failed", "Failed", MB_OK);
        }
            // Get image data of bitmap for Clipboard
        int gb = ::GetDIBits(dc.m_hDC, hBitmap2, 0, (int)m_Dibhead.biHeight, ptr, info2, DIB_RGB_COLORS);
        if (gb == ERROR_INVALID_PARAMETER || gb == 0)
        {
            ::MessageBox(m_hWnd, "GetDIBits has failed", "Failed", MB_OK);
        }
        if (m_bIscut)    //If Cut, does this.
        {
            LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB
            lpbmi = (LPBITMAPINFOHEADER)lpDIBHdr;
                // Make selection box image white
            ::PatBlt(hdcMem, pc.x, pc.y, (int)m_Dibhead.biWidth, (int)m_Dibhead.biHeight, WHITENESS);//clear contend of local bitmap
                // Make white dib for selection box
            ::GetDIBits(dc.m_hDC, hBitmap, 0, (int)lpbmi->biHeight, lpDIBBits, (LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS);
            pDoc->SetModifiedFlag(TRUE);
            m_bIscut = FALSE;
            ::InvalidateRect(this->m_hWnd, NULL, FALSE);
        }
        ::GlobalUnlock((HGLOBAL)m_hBitstore2);

        /*pData->CacheGlobalData(CF_DIB, m_hBitstore2);//For test
        pData->SetClipboard();*/

        ::EmptyClipboard();
        ::SetClipboardData(CF_DIB, CopyHandle((HANDLE)m_hBitstore2));
        ::CloseClipboard();

        ::GlobalFree((HGLOBAL)m_hBitstore2);
        ::DeleteDC(dc);
        ::DeleteDC(hdcMem);
        ::DeleteObject(hBitmap);
        ::GlobalUnlock((HGLOBAL)hDIB);
        ::DeleteDC(hdcMem2);
        ::DeleteObject(hBitmap2);
        EndWaitCursor();
    }
}
c++ visual-c++ mfc clipboard clipboard-interaction
© www.soinside.com 2019 - 2024. All rights reserved.