2

首先这不是MFC。这是我一直在处理的 GUI 的裁剪版本:

在此处输入图像描述

如您所见,选项卡控件上方有一个位图图像(它使用默认窗口的句柄),我将其称为“蓝色位图”我没有问题,它运行良好。我遇到的问题是另一个位图(来自磁盘上的位图文件)设置为子窗口的背景(更具体地说是选项卡控件子窗口),替换灰色。以下是我尝试将位图设置为子窗口(选项卡)的背景的一些事情。

1) 我使用了与将蓝色位图分配给窗口相同的方法,首先使用 LoadImage 导入位图,如下所示:

index->hbmBitmapBanner = (HBITMAP)LoadImage(index->hInstance,L"Images\\horizontal.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);

然后在 WM_PAINT 消息中:

    case WM_PAINT:
    {
        PAINTSTRUCT ps1;
        if (BeginPaint(WINDOWHANDLE,&ps1))
        {
            HDC hdcBanner = CreateCompatibleDC(ps1.hdc);
            HBITMAP hbmOldHorizontal = (HBITMAP)SelectObject(hdcBanner,index->hbmBitmapBanner); // banner
            BitBlt(ps1.hdc,0,0,516,101,hdcBanner,5,0,SRCCOPY);
            SelectObject(hdcBanner,hbmOldHorizontal);
            DeleteDC(hdcBanner);
            EndPaint(WINDOWHANDLE,&ps1);
        }
        break;
    }

该代码成功地将蓝色位图设置到窗口中,但没有成功地将另一个位图设置到窗口中(当然,蓝色位图的变量被替换,大小和方向也发生了变化)。它根本没有在屏幕上显示位图,窗口保持不变,但没有任何功能失败。另外,当我交换文件位置时,它会将位图加载到蓝色位图所在的位置,因此加载功能肯定没有失败。

2) 使用上面的代码,我尝试将BeginPaint的第一个参数改成选项卡控件框的窗口句柄,再次证明没有用,窗口保持不变。我还尝试将 BeginPaint 的第一个参数更改为显示在信息选项卡上的子窗口,这导致子窗口(它是一个组框)消失,但窗口上仍然没有出现位图。

3)作为最后的手段,我愚蠢地试图在子窗口上使用这个功能

SetClassLongPtr(tab->hTabIndex[0],GCLP_HBRBACKGROUND,(DWORD)GetStockObject(BLACK_BRUSH));

当然,它没有用


如果它有任何用处,以下是我在窗口中创建选项卡的方式:

TCITEM tie = {0};     
tab->hTab = CreateWindowEx(0,WC_TABCONTROL,L"",WS_CHILD | WS_VISIBLE,0,101,600,400,                    
        WINDOWHANDLE,NULL,(HINSTANCE)GetWindowLong(WINDOWHANDLE,GWLP_HINSTANCE),NULL   
    );

是主选项卡控件,后面依次插入单个选项卡(即信息选项卡)

    TCHAR pszTab1 [] = L"Information";  // tab1's text 
tie.pszText = pszTab1;  // the tab's text/caption
TabCtrl_InsertItem(tab->hTab, 0, &tie); // insert the tab

附加信息:除此之外,选项卡控件和窗口正在完美地工作/交互。我只在一个选项卡上测试/尝试这个,因为我知道它是否在一个选项卡上工作,那么它将在所有选项卡上工作,从而节省时间。

我有我旁边的 Charles Petzold 编写的 Programming For Windows Fifth Edition 作为参考,并且有相当大的部分关于位图,但他没有谈论将位图加载到子窗口,他得到的最接近的是使用菜单中的位图,与窗口完全不同。

4

1 回答 1

3

我认为这里的问题是 Windows 公共控件不通过主线程的窗口过程与您的应用程序交互,而是通过它们自己的(系统定义的)窗口过程。

因此,例如,当您的选项卡窗口重绘自身时,它不会响应到达代码中定义的窗口过程的 WM_PAINT 消息。您应该能够通过检查传递给您的窗口过程的消息的窗口句柄(例如 WM_PAINT)来验证自己是否如此。

如果您希望“利用”公共控件的默认行为,则必须对其进行“子类化”(参见此处),但根据我的经验,尝试更改重绘行为通常是有问题的。

在选项卡控件的情况下,最好的办法是创建一个大小与选项卡控件的客户区大小一致的子窗口数组,并安排在任何时候显示的窗口对应于选定的选项卡。

如果您使用 C++,您可能会考虑创建一个基类来包装这些处理​​背景(位图)绘图的窗口。然后,您可以派生一系列包装器来处理每个单独的选项卡。我过去就使用过这种方法并且效果很好。

记住选项卡控件的选项卡并不延伸到整个控件的客户区,而只是字面上的选项卡本身,这可能会有所帮助。我不记得细节,但我认为它们是由控件在内部处理的,并且以任何方式操作它们都是相当诡计的,即使控件是子类化的——这可能是错误的。

希望有帮助。

干杯,伊恩。

于 2013-01-12T11:42:32.083 回答