windows程序设计「BLOWUP.C」范例分析笔记

本文档分析了BLOWUP.C,一个Windows平台的视频放大程序。通过讲解源代码,展示了如何利用WinAPI进行窗口创建、消息处理、鼠标交互以及位图操作,包括获取桌面窗口设备上下文、位图复制、反向颜色等技术。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*---------------------------------------

   BLOWUP.C -- Video Magnifier Program

               (c) Charles Petzold, 1998

  ---------------------------------------*/

 

#include <windows.h>

#include <stdlib.h>      // for abs definition

#include "resource.h"

 

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

 

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

                    PSTR szCmdLine, int iCmdShow)

{

     static TCHAR szAppName [] = TEXT ("Blowup") ;

     HACCEL       hAccel ;

     HWND         hwnd ;

     MSG          msg ;

     WNDCLASS     wndclass ;

 

     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;

     wndclass.lpfnWndProc   = WndProc ;

     wndclass.cbClsExtra    = 0 ;

     wndclass.cbWndExtra    = 0 ;

     wndclass.hInstance     = hInstance ;

     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;

     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;

     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;

     wndclass.lpszMenuName  = szAppName ;

     wndclass.lpszClassName = szAppName ;

    

     if (!RegisterClass (&wndclass))

     {

          MessageBox (NULL, TEXT ("This program requires Windows NT!"),

                      szAppName, MB_ICONERROR) ;

          return 0 ;

     }

    

     hwnd = CreateWindow (szAppName, TEXT ("Blow-Up Mouse Demo"),

                          WS_OVERLAPPEDWINDOW,

                          CW_USEDEFAULT, CW_USEDEFAULT,

                          CW_USEDEFAULT, CW_USEDEFAULT,

                          NULL, NULL, hInstance, NULL) ;

 

     ShowWindow (hwnd, iCmdShow) ;

     UpdateWindow (hwnd) ;

 

     hAccel = LoadAccelerators (hInstance, szAppName) ;

 

     while (GetMessage (&msg, NULL, 0, 0))

     {

          if (!TranslateAccelerator (hwnd, hAccel, &msg))

          {

               TranslateMessage (&msg) ;

               DispatchMessage (&msg) ;

          }

     }

     return msg.wParam ;

}

 

void InvertBlock (HWND hwndScr, HWND hwnd, POINT ptBeg, POINT ptEnd)

{

     HDC hdc ;

          // 获取桌面窗口的显示设备上下文环境的句柄

          // DCX_CACHE 从高速缓存中返回设备上下文环境,从本质上覆盖CS_OWNDCCS_CLASSDC

          // DCX_LOCKWINDOWUPDATE 指明可以在锁定期间进行绘制

     hdc = GetDCEx (hwndScr, NULL, DCX_CACHE | DCX_LOCKWINDOWUPDATE) ;

          // 将用户坐标转换成屏幕坐标

     ClientToScreen (hwnd, &ptBeg) ;

     ClientToScreen (hwnd, &ptEnd) ;

          // 绘制给定的矩形区域 DSTINVERT标记将目标矩形颜色反向

     PatBlt (hdc, ptBeg.x, ptBeg.y, ptEnd.x - ptBeg.x, ptEnd.y - ptBeg.y,

             DSTINVERT) ;

     ReleaseDC (hwndScr, hdc) ;

}

 

HBITMAP CopyBitmap (HBITMAP hBitmapSrc)

{

     BITMAP  bitmap ;

     HBITMAP hBitmapDst ;

     HDC     hdcSrc, hdcDst ;

 

          // 获取位图信息,并建立新位图

     GetObject (hBitmapSrc, sizeof (BITMAP), &bitmap) ;

     hBitmapDst = CreateBitmapIndirect (&bitmap) ;

          // 建立兼容内存设备环境,并选进位图

     hdcSrc = CreateCompatibleDC (NULL) ;

     hdcDst = CreateCompatibleDC (NULL) ;

 

     SelectObject (hdcSrc, hBitmapSrc) ;

     SelectObject (hdcDst, hBitmapDst) ;

 

     BitBlt (hdcDst, 0, 0, bitmap.bmWidth, bitmap.bmHeight,

             hdcSrc, 0, 0, SRCCOPY) ;

 

     DeleteDC (hdcSrc) ;

     DeleteDC (hdcDst) ;

 

     return hBitmapDst ;

}

 

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

     static BOOL    bCapturing, bBlocking ;

     static HBITMAP hBitmap ;

     static HWND    hwndScr ;

     static POINT   ptBeg, ptEnd ;

     BITMAP         bm ;

     HBITMAP        hBitmapClip ;

     HDC            hdc, hdcMem ;

     int            iEnable ;

     PAINTSTRUCT    ps ;

     RECT           rect ;

 

     switch (message)

     {

          // 处理鼠标左键按键

     case WM_LBUTTONDOWN:

          if (!bCapturing)

          {

                    // 锁定桌面窗口        // 获取桌面窗口设备句柄

               if (LockWindowUpdate (hwndScr = GetDesktopWindow ()))

               {

                    bCapturing = TRUE ;

                    // 设置鼠标捕获

                    SetCapture (hwnd) ;

                   // 设置鼠标光标形状

                    SetCursor (LoadCursor (NULL, IDC_CROSS)) ;

               }

               else

                    MessageBeep (0) ;

          }

          return 0 ;

 

         // 处理鼠标右键按下

     case WM_RBUTTONDOWN:

          // 在鼠标左键按下的情况下才执行

          if (bCapturing)

          {

               bBlocking = TRUE ;

              // 取得鼠标右键按下时的坐标

               ptBeg.x = LOWORD (lParam) ;

               ptBeg.y = HIWORD (lParam) ;

               ptEnd = ptBeg ;

              // 使选择矩形颜色反向

               InvertBlock (hwndScr, hwnd, ptBeg, ptEnd) ;

          }

          return 0 ;

 

         // 处理鼠标移动

     case WM_MOUSEMOVE:

        // 在鼠标左右键均按下的情况下执行

          if (bBlocking)

          {

 

               InvertBlock (hwndScr, hwnd, ptBeg, ptEnd) ;

               ptEnd.x = LOWORD (lParam) ;

               ptEnd.y = HIWORD (lParam) ;

               InvertBlock (hwndScr, hwnd, ptBeg, ptEnd) ;

          }

          return 0 ;

 

          // 处理鼠标左右键释放

     case WM_LBUTTONUP:

     case WM_RBUTTONUP:

         // 如果鼠标右键释放则执行

          if (bBlocking)

          {

               // 反转选择矩形颜色,获取释放时鼠标坐标

               InvertBlock (hwndScr, hwnd, ptBeg, ptEnd) ;

               ptEnd.x = LOWORD (lParam) ;

               ptEnd.y = HIWORD (lParam) ;

 

               if (hBitmap)

               {

                    DeleteObject (hBitmap) ;

                    hBitmap = NULL ;

               }

               // abs 求整数的绝对值

               hdc = GetDC (hwnd) ;

               hdcMem = CreateCompatibleDC (hdc) ;

               hBitmap = CreateCompatibleBitmap (hdc,

                                   abs (ptEnd.x - ptBeg.x),

                                   abs (ptEnd.y - ptBeg.y)) ;

 

               SelectObject (hdcMem, hBitmap) ;

 

               // 拉伸显示到内存设备环境中

               StretchBlt (hdcMem, 0, 0, abs (ptEnd.x - ptBeg.x),

                                         abs (ptEnd.y - ptBeg.y),

                           hdc, ptBeg.x, ptBeg.y, ptEnd.x - ptBeg.x,

                                                  ptEnd.y - ptBeg.y, SRCCOPY) ;

 

               DeleteDC (hdcMem) ;

               ReleaseDC (hwnd, hdc) ;

               InvalidateRect (hwnd, NULL, TRUE) ;

          }

          if (bBlocking || bCapturing)

          {

               bBlocking = bCapturing = FALSE ;

               // 修改鼠标光标,释放鼠标捕获,解锁桌面窗口

               SetCursor (LoadCursor (NULL, IDC_ARROW)) ;

               ReleaseCapture () ;

               LockWindowUpdate (NULL) ;

          }

          return 0 ;

 

          // 菜单准备弹出时,处理可选项

     case WM_INITMENUPOPUP:

          // 判断剪贴板中CF_BITMAP数据是否存在,依此修改菜单可选项

          iEnable = IsClipboardFormatAvailable (CF_BITMAP) ?

                              MF_ENABLED : MF_GRAYED ;

 

          EnableMenuItem ((HMENU) wParam, IDM_EDIT_PASTE, iEnable) ;

          // 判断位图是否建立,依此修改菜单可选项

          iEnable = hBitmap ? MF_ENABLED : MF_GRAYED ;

 

          EnableMenuItem ((HMENU) wParam, IDM_EDIT_CUT,    iEnable) ;

          EnableMenuItem ((HMENU) wParam, IDM_EDIT_COPY,   iEnable) ;

          EnableMenuItem ((HMENU) wParam, IDM_EDIT_DELETE, iEnable) ;

          return 0 ;

 

     case WM_COMMAND:

          switch (LOWORD (wParam))

          {

          case IDM_EDIT_CUT:

          case IDM_EDIT_COPY:

               if (hBitmap)

               {

                    hBitmapClip = CopyBitmap (hBitmap) ;

                    // 打开、清空和更新剪贴板

                    OpenClipboard (hwnd) ;

                    EmptyClipboard () ;

                    SetClipboardData (CF_BITMAP, hBitmapClip) ;

               }

               if (LOWORD (wParam) == IDM_EDIT_COPY)

                    return 0 ;

              // 如果是 剪切 指令,则继续执行

          case IDM_EDIT_DELETE:

               if (hBitmap)

               {

                    DeleteObject (hBitmap) ;

                    hBitmap = NULL ;

               }

               InvalidateRect (hwnd, NULL, TRUE) ;

               return 0 ;

 

          case IDM_EDIT_PASTE:

               if (hBitmap)

               {

                    DeleteObject (hBitmap) ;

                    hBitmap = NULL ;

               }

               // 获取剪贴板中的位图数据句柄

               OpenClipboard (hwnd) ;

               hBitmapClip = GetClipboardData (CF_BITMAP) ;

 

               // 拷贝剪贴板中的位图数据到程序内存

               if (hBitmapClip)

                    hBitmap = CopyBitmap (hBitmapClip) ;

 

               CloseClipboard () ;

               InvalidateRect (hwnd, NULL, TRUE) ;

               return 0 ;

          }

          break ;

 

     case WM_PAINT:

          hdc = BeginPaint (hwnd, &ps) ;

 

          if (hBitmap)

          {

                              // 取得窗口大小

               GetClientRect (hwnd, &rect) ;

 

               hdcMem = CreateCompatibleDC (hdc) ;

               SelectObject (hdcMem, hBitmap) ;

                               // 取得位图信息

               GetObject (hBitmap, sizeof (BITMAP), (PSTR) &bm) ;

               // 设置指定设备环境中的位图拉伸模式

               // COLORONCOLOR:该模式删除所有消除的像素行,不保留其信息

               SetStretchBltMode (hdc, COLORONCOLOR) ;

 

               StretchBlt (hdc,    0, 0, rect.right, rect.bottom,

                           hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY) ;

 

               DeleteDC (hdcMem) ;

          }

          EndPaint (hwnd, &ps) ;

          return 0 ;

 

     case WM_DESTROY:

          if (hBitmap)

               DeleteObject (hBitmap) ;

 

          PostQuitMessage (0) ;

          return 0 ;

     }

     return DefWindowProc (hwnd, message, wParam, lParam) ;

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值