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

将视觉效果应用于桌面 - Shoot

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.46/5 (13投票s)

2003年8月1日

3分钟阅读

viewsIcon

128353

downloadIcon

2918

本文讨论了应用程序如何通过复制桌面内容、对其应用效果然后重新显示来将视觉效果应用于桌面。

Sample Image

引言

本文讨论了应用程序如何通过复制桌面内容,使用 GDI 函数对其应用效果,然后重新显示来将视觉效果应用于桌面。此外,此应用程序还演示了如何使用 Win32 API 播放 wav 文件。

当您对计算机感到沮丧并想从字面上射击它的脑髓时,Shoot 会派上用场。该应用程序运行时,会将您的鼠标指针转换为枪的瞄准器,无论您点击哪里,它都会发出枪声,并在桌面上烧出一个洞。要关闭应用程序,只需按 Esc 键

背景

像所有其他窗口一样,桌面窗口也具有与其关联的设备上下文。 Win32 API GetDCEx(...) 可用于获取此桌面设备上下文的句柄。使用此句柄,您可以将桌面窗口内容复制到应用程序的某个设备上下文。然后,使用 GDI 操作的任意组合,可以将各种视觉效果应用于它。

使用代码

我们从对话框类的构造函数中开始复制桌面窗口,因为我们需要在此应用程序的窗口出现之前执行此操作。我们首先获取桌面设备上下文的句柄,然后将其转换为指向 CDC 对象的指针。我们还获取屏幕分辨率。

CDC *pDesktopDC = CDC::FromHandle (::GetDCEx(NULL, NULL, 0));
int screenMaxX = GetSystemMetrics(SM_CXSCREEN);
int screenMaxY = GetSystemMetrics(SM_CYSCREEN);

然后,我们在内存中创建一个与桌面设备上下文兼容的设备上下文。

m_pProcDC = new CDC;
m_pProcDC->CreateCompatibleDC (pDesktopDC);

创建内存设备上下文时,会选择一个 1x1 像素大小的位图,因此对其执行的 GDI 操作不会产生所需的效果。我们通过创建一个与桌面尺寸相同的位图并将其选择到内存设备上下文中来规避此问题。

m_pBMP = new CBitmap;
m_pBMP->CreateCompatibleBitmap (pDesktopDC, screenMaxX, screenMaxY);
m_pProcDC->SelectObject (m_pBMP);

内存设备上下文现在可以使用了,我们可以将桌面设备上下文的内容复制到其中。

 m_pProcDC->BitBlt(0, 0, screenMaxX, screenMaxY, pDesktopDC, 0, 0, SRCCOPY);

完成此操作后,您可以将任何视觉效果应用于内存设备上下文,然后重新显示它。

但是,在此应用程序中,我们现在不会应用视觉效果。我们需要在用户单击时在屏幕上创建一个弹痕。为此,我们使用名为 IDB_SHOTMARK 的位图资源,它类似于枪击痕迹。要使用此位图,我们加载它并将其选择到内存中创建的另一个设备上下文中。

m_pShotDC = new CDC;
m_pShotDC->CreateCompatibleDC(pDesktopDC);

m_pShotBmp = new CBitmap;
m_pShotBmp->LoadBitmap ( IDB_SHOTMARK );

m_pShotDC->SelectObject ( m_pShotBmp );

当我们完成复制桌面内容和加载位图后,我们就可以显示它们了。

OnInitDialog 中,我们通过使对话框具有桌面大小并通过调用 SetWindowPos 使其始终保持在最前面来使对话框覆盖整个桌面。

::SetWindowPos( this->GetSafeHwnd(), HWND_TOPMOST, 0, 0,
                 GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
                 SWP_SHOWWINDOW);

我们还通过加载枪的取景器光标(这是另一个资源)来使其做好准备。

HINSTANCE hInstResource = AfxFindResourceHandle (MAKEINTRESOURCE(IDC_TF),
                                                  RT_GROUP_CURSOR);
m_hCursor = ::LoadCursor(hInstResource, MAKEINTRESOURCE(IDC_TF));

OnPaint 处理程序中,我们通过将其从内存中的设备上下文(我们之前存储的地方)复制到对话框的设备上下文来显示桌面窗口。

CDC *pDC = GetDC();
pDC->BitBlt (0, 0, screenMaxX, screenMaxY, m_pProcDC, 0, 0, SRCCOPY );
ReleaseDC(pDC);

剩下的唯一一件事是显示枪击标记并在用户单击时发出声音。为此,我们处理消息 WM_LBUTTONDOWN,在该消息中,我们将加载到 m_pShotDC 设备上下文中的枪击位图的内容复制到用户单击的位置。我们还使用 PlaySound 函数播放 wav 文件。要使用此函数,您需要将 VC98\Lib\WINMM.LIB 与您的应用程序链接,并在您的应用程序中包含 mmsystem.h 头文件。

void CShootDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
 ...
 //  Show gunshot mark
 CDC *pDC = GetDC();
 pDC->BitBlt (point.x - 10, point.y - 10, 48, 48, m_pShotDC, 0, 0, SRCAND);
 ReleaseDC(pDC);
 ...

 //  Play gunshot sound
 ::PlaySound((LPCTSTR)soundFile, NULL,
             SND_FILENAME | SND_ASYNC | SND_NODEFAULT | SND_PURGE);
 ...

}

关注点

该项目假定 winmm.lib 可用作 ..\..\VC98\Lib\WINMM.LIB。因此,您需要在构建应用程序之前将 shoot 源提取到 MyProjects 文件夹中或更改相对路径。

该应用程序假定 gunshot.wav 文件与可执行文件位于同一文件夹中。如果找不到 wav 文件,则不会发出枪声。

历史

  • v1.0 - 这是初始版本。
© . All rights reserved.