Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用STM_SETIMAGE之前设置位图的透明度_C++_Winapi_Bitmap - Fatal编程技术网

C++ 使用STM_SETIMAGE之前设置位图的透明度

C++ 使用STM_SETIMAGE之前设置位图的透明度,c++,winapi,bitmap,C++,Winapi,Bitmap,我有一个静态控件,通过使用位图将STM_图像发送到该控件来设置图像。这很好,但我希望位图有一个透明的背景。我有以下代码: case WM_PAINT: { HBITMAP hbmBmp, hbmMask; BITMAP bm; PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); HWND hCtrl = GetDlgItem(hWnd, ID_BUTTONNEWGAME); hbmBmp =

我有一个静态控件,通过使用位图将STM_图像发送到该控件来设置图像。这很好,但我希望位图有一个透明的背景。我有以下代码:

case WM_PAINT:
{
    HBITMAP hbmBmp, hbmMask;
    BITMAP bm;
    PAINTSTRUCT ps;

    HDC hdc = BeginPaint(hWnd, &ps);
    HWND hCtrl = GetDlgItem(hWnd, ID_BUTTONNEWGAME);
    hbmBmp = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_NEWGAMEBUTTONBITMAP));
    GetObject(hbmBmp, sizeof(BITMAP), &bm);
    hbmMask = CreateBitmapMask(hbmBmp, RGB(0, 0, 0));
    HDC hDCMem = CreateCompatibleDC(hdc);
    HDC hDCMem2 = CreateCompatibleDC(hdc);
    HDC hdcResult = CreateCompatibleDC(hdc);

    SelectObject(hDCMem, hbmMask);
    BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hDCMem, 0, 0, SRCAND);

    SelectObject(hDCMem, hbmBmp);
    BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hDCMem, 0, 0, SRCPAINT);

    // At this point I can see the bitmap with a transparent background at (0,0)
    // The following code attempts to copy from hdc into a memory DCand to form a new bitmap 
    //that I use in the STM_SETIMAGE message

    HBITMAP newBitmap = CreateCompatibleBitmap(hdc, bm.bmWidth, bm.bmHeight); // create blank bitmap
    SelectObject(hdcResult, newBitmap); // store in memory DC
    BitBlt(hdcResult, 0, 0, bm.bmWidth, bm.bmHeight, hdc, 0, 0, SRCCOPY); // copy from hdc to memory DC

    // This line is just for checking that hdcResult contains the correct data
    // It copies back from the memory DC into hdc to the right of the original bitmap
    // I now see two bitmaps with transparent bitmaps next to each other as I expected
    BitBlt(hdc, bm.bmWidth, 0, bm.bmWidth, bm.bmHeight, hdcResult, 0, 0, SRCCOPY); 
    EndPaint(hWnd, &ps);

    // sending this does not set the bitmap on the static control
    // I do not see anything where the control should be
    SendMessage(hCtrl, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)newBitmap);
}
break;
case WM_CREATE:
{
    HWND newGameText = CreateWindowW(
        L"STATIC",
        L"",
        WS_VISIBLE | WS_CHILD | SS_BITMAP | SS_NOTIFY,  // Styles 
        150,         // x position 
        150,         // y position 
        74,        //  width
        24,        //  height
        hWnd,     // Parent window
        (HMENU)ID_BUTTONNEWGAME,
        (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
        NULL);      // Pointer not needed.
}
break;
静态控件是使用SS_位图样式在以下代码中创建的:

case WM_PAINT:
{
    HBITMAP hbmBmp, hbmMask;
    BITMAP bm;
    PAINTSTRUCT ps;

    HDC hdc = BeginPaint(hWnd, &ps);
    HWND hCtrl = GetDlgItem(hWnd, ID_BUTTONNEWGAME);
    hbmBmp = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_NEWGAMEBUTTONBITMAP));
    GetObject(hbmBmp, sizeof(BITMAP), &bm);
    hbmMask = CreateBitmapMask(hbmBmp, RGB(0, 0, 0));
    HDC hDCMem = CreateCompatibleDC(hdc);
    HDC hDCMem2 = CreateCompatibleDC(hdc);
    HDC hdcResult = CreateCompatibleDC(hdc);

    SelectObject(hDCMem, hbmMask);
    BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hDCMem, 0, 0, SRCAND);

    SelectObject(hDCMem, hbmBmp);
    BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hDCMem, 0, 0, SRCPAINT);

    // At this point I can see the bitmap with a transparent background at (0,0)
    // The following code attempts to copy from hdc into a memory DCand to form a new bitmap 
    //that I use in the STM_SETIMAGE message

    HBITMAP newBitmap = CreateCompatibleBitmap(hdc, bm.bmWidth, bm.bmHeight); // create blank bitmap
    SelectObject(hdcResult, newBitmap); // store in memory DC
    BitBlt(hdcResult, 0, 0, bm.bmWidth, bm.bmHeight, hdc, 0, 0, SRCCOPY); // copy from hdc to memory DC

    // This line is just for checking that hdcResult contains the correct data
    // It copies back from the memory DC into hdc to the right of the original bitmap
    // I now see two bitmaps with transparent bitmaps next to each other as I expected
    BitBlt(hdc, bm.bmWidth, 0, bm.bmWidth, bm.bmHeight, hdcResult, 0, 0, SRCCOPY); 
    EndPaint(hWnd, &ps);

    // sending this does not set the bitmap on the static control
    // I do not see anything where the control should be
    SendMessage(hCtrl, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)newBitmap);
}
break;
case WM_CREATE:
{
    HWND newGameText = CreateWindowW(
        L"STATIC",
        L"",
        WS_VISIBLE | WS_CHILD | SS_BITMAP | SS_NOTIFY,  // Styles 
        150,         // x position 
        150,         // y position 
        74,        //  width
        24,        //  height
        hWnd,     // Parent window
        (HMENU)ID_BUTTONNEWGAME,
        (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
        NULL);      // Pointer not needed.
}
break;

我是否需要将位图复制到控件的特定位置?这在设备上下文中似乎不合理,还是我做了一些完全不可能/愚蠢的事情?

我认为制作控件SS_位图并处理WM_PAINT消息没有意义。发送一个STM_SETIMAGE,即更改位图以响应每个绘画请求WM_paint消息,这是一个相当过分的做法,不是吗?完成后,您应该删除所有创建的DCs和位图以及STM_SETIMAGE消息返回的值,该消息是传递给控件的前一个位图

要么制作控件SS_位图并使用STM_SETIMAGE,要么绘制它的所有者并处理WM_DRAWITEM消息

您可能还需要检查TransparentBlt函数

我在这里添加了一些工作示例的代码。简单易实现,只需编写很少的代码。所有者绘制的大小写确实绘制了带有透明区域的位图。所有这些都是使用老式的GDI而不是GDI+函数完成的

在本例中,我创建了一个包含三个静态控件的对话框,它们以不同的方式实现:

IDC_IMG1:SS_位图样式,在资源文件中设置图像 IDC_IMG2:SS_位图样式最初没有图像,图像设置为STM_SETIMAGE消息 IDC_IMG3:SS_OWNERDRAW样式,将位图与透明区域分离 资源文件内容:

源代码:

结果如下:

我知道我应该在使用后删除设备上下文。您没有创建具有alpha透明度的位图。对BitBlt的前两个调用通过只写入未被遮罩的像素来创建透明效果。完成后,未更改的像素仍保留其背景色。如果需要透明度,请与图像图标一起使用。图标支持透明,甚至可能是alpha透明。谢谢,但我在按钮上看不到任何东西,甚至没有透明的位图。我将编辑OP以使其更清晰。您的静态控件是否具有SS_位图样式?顺便问一下,既然它的ID是ID_BUTTONNEWGAME,那么它真的是一个静态控件吗?在传递之前,从设备上下文中选择newBitmap可能也是一个好主意。否则它归设备上下文所有。一旦您执行正确的清理,这将产生影响。是的,控件是使用SS_位图样式创建的。我将把创建代码添加到OP中。这并不能解决这个问题。将静态控件的样式设置为包含SS_位图并处理其父控件的WM_绘制完全没有问题。透明技术试图解决一个根本不存在的问题。另外,这也不会产生一个透明的位图。嗯,我不同意你在这里所说的一切。当然,绘制SS_位图静态控件是错误的,因为这些控件具有资源文件中定义的或通过STM_SETIMAGE msg分配的关联位图;他们自己也会画画,那么把他们画过来又有什么意义呢?每次绘画请求时,图像是否应该更改STM_SETIMAGE的实际功能?不,不,不!!!而透明技术试图解决一个根本不存在的问题???当然它确实存在,而这正是OP所追求的。这很容易,只需一个电话!这与意见无关。问题中代码的目的是动态生成位图,并将其设置为静态控件的图像。WM_绘制处理程序不会绘制静态控件,因为它不是作为所有者绘制的控件创建的。在WM_PAINT处理程序中设置位图并不理想WM_INITDIALOG更合适。但通过适当的资源管理,这不一定是错误的。TransparentBlt没有帮助。您仍然假设问题中的代码正在呈现静态控件。事实并非如此,所有可以推断的信息都在那里。这就是为什么我对你的答案投了-1票。我不知道,为什么会有人投赞成票。它没有解决这个问题。哦,是的,它解决了!实际上,我已经提出了两种选择。Esp业主制定的解决方案易于实施。另一个更难,因为必须处理ico和PNG,而这些工具几乎不支持。