65.9K
CodeProject 正在变化。 阅读更多。
Home

在 MDI 主框架背景上绘制图像

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (11投票s)

2002年3月27日

2分钟阅读

viewsIcon

159809

downloadIcon

3934

本文解释了如何使用窗口子类化在 MDI 主框架背景上绘制图像。

Sample Image - Image1.jpg

引言

很久以前,我使用Altera Max Plus II设计简单的电子芯片。我注意到这个应用程序在主框架背景上绘制了一个公司徽标。有一次我比平时有更多空闲时间,我想自己实现它。这篇文章就是结果:)

实现

所以您可能想知道如何在MDI应用程序的背景窗口上绘制图像。首先,您必须对要绘制的窗口进行子类化。为此,请调用 GetWindowLong(hMain, GWL_WNDPROC)。此函数返回指向旧窗口过程的指针,我们希望将其存储以供将来使用。将此代码放在 CBackgroundImageApp::InitInstance() 中,就在显示主框架之前。

HWND hMain = pMainFrame->GetWindow(GW_CHILD)->GetSafeHwnd();
pfnOldWndProc = (WNDPROC)GetWindowLong(hMain, GWL_WNDPROC);
SetWindowLong(hMain, GWL_WNDPROC, (long)pfnNewWndProc);

现在我们已经对窗口进行了子类化,但是缺少窗口过程。现在就来编写它。窗口过程应该至少处理两个消息才能正常工作

  • WM_ERASEBKGND
  • WM_SIZE

第一条消息是在Windows希望应用程序绘制其背景时发送的 - 我们将使用它来绘制我们的图像。第二条消息也很重要,因为当您调整窗口大小时,图像也应该改变其大小以适应新的窗口大小。我们的窗口过程将如下所示

LRESULT CALLBACK pfnNewWndProc(HWND hwnd, 
       UINT uMsg, WPARAM wParam,LPARAM lParam)
{
    // local variables goes here

    switch (uMsg)   {
        case WM_SIZE :
            // ...
        case WM_ERASEBKGND :
            // ...
            return 1;
        default :
            return CallWindowProc(pfnOldWndProc,
                hwnd, uMsg, wParam, lParam);
    }
}

重要提示

WM_ERASEBKGND 案例返回1非常重要,因为它告诉Windows我们已经擦除了窗口,并且它无事可做,否则Windows将使用标准背景再次擦除此窗口,我想这并不是我们想要实现的。

那其他消息呢?

这就是我们使用存储的旧窗口过程指针的时刻。我们只需调用旧过程并返回其结果。所以让我们更仔细地看看 WM_SIZEWM_ERASEBKGND 案例。

WM_SIZE - 简单地通过向其发送 WM_ERASEBKGND 来强制窗口背景重新绘制自身

SendMessage(hwnd, WM_ERASEBKGND, (WPARAM)GetDC(hwnd), 0);
return 1;

WM_ERASEBKGND - 下面的代码将简单地 BitBlt 位图。因为窗口大小通常很少与图像大小相同,所以 BitBlt() 变为 StretchBlt()。最后它看起来如下

hcompdc = CreateCompatibleDC(hdc);
SelectObject(hcompdc, hBmp);
GetClientRect(hwnd, &rect);

if (0 == StretchBlt(hdc, 
    rect.left, rect.top, rect.right, rect.bottom,
    hcompdc, 0, 0, 1152, 864, SRCCOPY))
    MessageBox(hwnd, "error",
        "while StretchBlt", MB_OK);

DeleteDC(hcompdc);
return 1;

其中

  • hdc, hcompdc - 设备上下文
  • hBmp - 位图句柄

调用 DeleteDC() 非常重要,因为我们不想导致内存泄漏。

最后说明

此解决方案的性能在很大程度上取决于操作系统、已安装的显卡以及窗口大小。 在我的情况下,Windows 98 是比 Windows 2000 更好的选择。 在第二个系统上,重新绘制图像需要更长的时间才能让用户感觉舒适。 在 Windows 98 上运行的应用程序看起来非常好。 我的图形设备是 Geforce 2 GTS。 如果您有其他系统或配置的经验,请在文章的讨论区下方发布。 StretchBlt 函数在系统之间也有所不同。 这一次,Windows 98 中使用的也更好。

© . All rights reserved.