Windows程序设计 HELLOBIT.C -- SKETCH.C 范例分析笔记

/*-----------------------------------------
   HELLOBIT.C – 在内存设备内容中的位图上输出
                文字
  -----------------------------------------*/

#include <windows.h>
#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 ( "HelloBit") ;
     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 ( "HelloBit" ),
                          WS_OVERLAPPEDWINDOW ,
                          CW_USEDEFAULT , CW_USEDEFAULT ,
                          CW_USEDEFAULT , CW_USEDEFAULT ,
                          NULL , NULL , hInstance , NULL) ;

     ShowWindow ( hwnd , iCmdShow) ;
     UpdateWindow ( hwnd) ;

     while ( GetMessage ( & msg , NULL , 0 , 0))
     {
          TranslateMessage ( & msg) ;
          DispatchMessage ( & msg) ;
     }
     return msg . wParam ;
}

LRESULT CALLBACK WndProc ( HWND hwnd , UINT message , WPARAM wParam , LPARAM lParam)
{
     static HBITMAP hBitmap ;
     static HDC     hdcMem ;
     static int     cxBitmap , cyBitmap , cxClient , cyClient , iSize = IDM_BIG ;
     static TCHAR * szText = TEXT ( " Hello, world! ") ;
     HDC            hdc ;
     HMENU          hMenu ;
     int            x , y ;
     PAINTSTRUCT    ps ;
     SIZE           size ;
    
     switch ( message)
     {
     case WM_CREATE:
          hdc = GetDC ( hwnd) ; //取整个窗体的设备内容句柄
          hdcMem  = CreateCompatibleDC ( hdc) ; //建立与视讯显示器兼容的内存设备内容

          //计算字符串的高度和宽度的图素尺寸
          //lstrlen (szText) 计算字符串的字符数
          GetTextExtentPoint32 ( hdc , szText , lstrlen ( szText ), & size) ;
          cxBitmap = size . cx ;
          cyBitmap = size . cy ; //以字符串的宽度和高度来设定位图大小

          //建立与设备内容兼容的位图,大小为上面计算的字符串宽高
          hBitmap = CreateCompatibleBitmap ( hdc , cxBitmap , cyBitmap) ;

          ReleaseDC ( hwnd , hdc) ; //释放设备内容句柄

          SelectObject ( hdcMem , hBitmap) ; //将建立的位图选进内存设备内容

          //在内存设备内容上输出字符串
          TextOut ( hdcMem , 0 , 0 , szText , lstrlen ( szText)) ;
          return 0 ;

     case WM_SIZE:
          cxClient = LOWORD ( lParam) ;
          cyClient = HIWORD ( lParam) ;
          return 0 ;

     case WM_COMMAND:
          hMenu = GetMenu ( hwnd) ; //取得窗体的菜单句柄

          switch ( LOWORD ( wParam))
          {
          case IDM_BIG:
          case IDM_SMALL:
              //删除iSize所对应的菜单的选取标记
               CheckMenuItem ( hMenu , iSize , MF_UNCHECKED) ;
               iSize = LOWORD ( wParam) ;   //读取当前选择的菜单项
               CheckMenuItem ( hMenu , iSize , MF_CHECKED) ; //标记当前选择的菜单项
               InvalidateRect ( hwnd , NULL , TRUE) ; //要求系统重绘整个窗体
               break ;
          }
          return 0 ;

     case WM_PAINT:
          hdc = BeginPaint ( hwnd , &ps) ;

          switch ( iSize)
          {
          case IDM_BIG: //拉伸位图到整个窗体
               StretchBlt ( hdc , 0 , 0 , cxClient , cyClient ,
                           hdcMem , 0 , 0 , cxBitmap , cyBitmap , SRCCOPY) ;
               break ;

          case IDM_SMALL: //平铺位图到窗体
               for ( y = 0 ; y < cyClient ; y += cyBitmap)
               for ( x = 0 ; x < cxClient ; x += cxBitmap)
               {
                    BitBlt ( hdc , x , y , cxBitmap , cyBitmap ,
                            hdcMem , 0 , 0 , SRCCOPY) ;
               }
               break ;
          }

          EndPaint ( hwnd , &ps) ;
          return 0 ;

     case WM_DESTROY:
          DeleteDC ( hdcMem) ; //删除内存设备内容
          DeleteObject ( hBitmap) ; //删除建立的位图
          PostQuitMessage ( 0) ;
          return 0 ;
     }
     return DefWindowProc ( hwnd , message , wParam , lParam) ;
}



/*-----------------------------------------
   HelloBit.rc – HELLOBIT.C资源文件
  -----------------------------------------*/
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH , SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE DISCARDABLE
BEGIN
    "resource.h /0 "
END

2 TEXTINCLUDE DISCARDABLE
BEGIN
    "#include ""afxres.h"" /r/n "
    " /0 "
END

3 TEXTINCLUDE DISCARDABLE
BEGIN
    " /r/n "
    " /0 "
END

#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Menu
//

HELLOBIT MENU DISCARDABLE
BEGIN
    POPUP "&Size"
    BEGIN
        MENUITEM "&Big" ,                        IDM_BIG , CHECKED
        MENUITEM "&Small" ,                      IDM_SMALL
    END
END

#endif    // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED




/*-----------------------------------------
   RESOURCE.H – HELLOBIT.C资源头文件
  -----------------------------------------*/
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by HelloBit.rc
//
#define IDM_BIG                         40001
#define IDM_SMALL                       40002

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        102
#define _APS_NEXT_COMMAND_VALUE         40003
#define _APS_NEXT_CONTROL_VALUE         1000
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

 



/*-----------------------------------------
   SKETCH.C – 在显示设备内容和内存设备内容
               上绘画
  -----------------------------------------*/

#include <windows.h>

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

int WINAPI WinMain ( HINSTANCE hInstance , HINSTANCE hPrevInstance ,
                    PSTR szCmdLine , int iCmdShow)
{
     static TCHAR szAppName [] = TEXT ( "Sketch") ;
     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  = NULL ;
     wndclass . lpszClassName = szAppName ;
    
     if ( ! RegisterClass ( & wndclass))
     {
          MessageBox ( NULL , TEXT ( "This program requires Windows NT!" ),
                      szAppName , MB_ICONERROR) ;
          return 0 ;
     }
    
     hwnd = CreateWindow ( szAppName , TEXT ( "Sketch" ),
                          WS_OVERLAPPEDWINDOW ,
                          CW_USEDEFAULT , CW_USEDEFAULT ,
                          CW_USEDEFAULT , CW_USEDEFAULT ,
                          NULL , NULL , hInstance , NULL) ;

     if ( hwnd == NULL)
     {
          MessageBox ( NULL , TEXT ( "Not enough memory to create bitmap!" ),
                      szAppName , MB_ICONERROR) ;
          return 0 ;
     }

     ShowWindow ( hwnd , iCmdShow) ;
     UpdateWindow ( hwnd) ;

     while ( GetMessage ( & msg , NULL , 0 , 0))
     {
          TranslateMessage ( & msg) ;
          DispatchMessage ( & msg) ;
     }
     return msg . wParam ;
}

void GetLargestDisplayMode ( int * pcxBitmap , int * pcyBitmap)
{
     DEVMODE devmode ;
     int     iModeNum = 0 ;

     * pcxBitmap = * pcyBitmap = 0 ;

     //用0来填充devmode内存区域
     ZeroMemory ( & devmode , sizeof ( DEVMODE)) ;

     devmode . dmSize = sizeof ( DEVMODE) ;
           //获取调用线程正运行在计算机的当前显示设备所有的图形模式信息,记录在devmode结构中
           //枚举调用,使其能获得当前显示设备的最大显示尺寸
     while ( EnumDisplaySettings ( NULL , iModeNum ++ , & devmode))
     {
          //取当前显示设备宽和高来设置位图尺寸,以像素为单位。MAX宏限制了该数不可为负数
          * pcxBitmap = max ( * pcxBitmap , ( int) devmode . dmPelsWidth) ;
          * pcyBitmap = max ( * pcyBitmap , ( int) devmode . dmPelsHeight) ;
     }
}

LRESULT CALLBACK WndProc ( HWND hwnd , UINT message , WPARAM wParam , LPARAM lParam)
{
     static BOOL    fLeftButtonDown , fRightButtonDown ;
     static HBITMAP hBitmap ;
     static HDC     hdcMem ;
     static int     cxBitmap , cyBitmap , cxClient , cyClient , xMouse , yMouse ;
     HDC            hdc ;
     PAINTSTRUCT    ps ;
    
     switch ( message)
     {
     case WM_CREATE:
          //调用自定义函数,取当前显示设备的最大尺寸来设定位图尺寸
          GetLargestDisplayMode ( & cxBitmap , & cyBitmap) ;

          hdc = GetDC ( hwnd) ; //取整个程序窗体的句柄
          //建立与显示设备兼容的位图
          hBitmap = CreateCompatibleBitmap ( hdc , cxBitmap , cyBitmap) ;
          //建立与显示设备兼容的内存设备内容
          hdcMem  = CreateCompatibleDC ( hdc) ;
          ReleaseDC ( hwnd , hdc) ; //删除窗体句柄

          //判断位图是否成功建立,如果CreateCompatibleBitmap调用失败,hBitmap值为NULL
          if ( ! hBitmap
          {
               //删除内存设备内容,并返回-1的错误消息
               DeleteDC ( hdcMem) ;
               return - 1 ;
          }
          //将建立的位图选进内存设备内容,等于是扩充内存设备内容
          SelectObject ( hdcMem , hBitmap) ;
          //将内存设备内容中的位图刷成白色
          PatBlt ( hdcMem , 0 , 0 , cxBitmap , cyBitmap , WHITENESS) ;
          return 0 ;

     case WM_SIZE:
          cxClient = LOWORD ( lParam) ;
          cyClient = HIWORD ( lParam) ;
          return 0 ;

     case WM_LBUTTONDOWN: //鼠标左键按下
          //如果鼠标右键已经释放,则为当前窗口捕获鼠标
          if ( ! fRightButtonDown)
               SetCapture ( hwnd) ;

          //获取鼠标光标相对于客户区域左上角的坐标
          xMouse = LOWORD ( lParam) ;
          yMouse = HIWORD ( lParam) ;
          //设置鼠标左键按下标记
          fLeftButtonDown = TRUE ;
          return 0 ;

     case WM_LBUTTONUP: //鼠标左键释放
          //如果鼠标左键按下标记被设置,则释放先前的鼠标捕获
          if ( fLeftButtonDown)
               SetCapture ( NULL) ;
          //设置鼠标左键释放标记
          fLeftButtonDown = FALSE ;
          return 0 ;
         
     case WM_RBUTTONDOWN: //鼠标右键按下
          //如果鼠标左键已经释放,则为当前窗口捕获鼠标
          if ( ! fLeftButtonDown)
               SetCapture ( hwnd) ;

          //获取鼠标光标相对于客户区域左上角的坐标
          xMouse = LOWORD ( lParam) ;
          yMouse = HIWORD ( lParam) ;
          //设置鼠标右键按下标记
          fRightButtonDown = TRUE ;
          return 0 ;
         
     case WM_RBUTTONUP: //鼠标右键释放
          //如果鼠标右键按下标记被设置,则释放先前的鼠标捕获
          if ( fRightButtonDown)
               SetCapture ( NULL) ;
          //设置鼠标右键释放标记
          fRightButtonDown = FALSE ;
          return 0 ;

     case WM_MOUSEMOVE:
          //如果鼠标左右键均已释放,则直接返回
          if ( ! fLeftButtonDown && ! fRightButtonDown)
               return 0 ;

          hdc = GetDC ( hwnd) ; //取得程序的整个窗体句柄

          //将相应的钢笔句柄选进设备内容中
          SelectObject ( hdc ,
               //鼠标左键按下则获取黑色钢笔句柄,否则取白色钢笔句柄
               GetStockObject ( fLeftButtonDown ? BLACK_PEN : WHITE_PEN)) ;

          //在内存设备内容中做相同操作
          SelectObject ( hdcMem ,
               GetStockObject ( fLeftButtonDown ? BLACK_PEN : WHITE_PEN)) ;

          //移动画线起始点到鼠标按下时所保存的位置
          MoveToEx ( hdc ,    xMouse , yMouse , NULL) ;
          MoveToEx ( hdcMem , xMouse , yMouse , NULL) ;

          //获取当前鼠标移动到的位置
          xMouse = ( short) LOWORD ( lParam) ;
          yMouse = ( short) HIWORD ( lParam) ;

          //在窗口和内存设备内容中的位图上划线
          LineTo ( hdc ,    xMouse , yMouse) ;
          LineTo ( hdcMem , xMouse , yMouse) ;

          ReleaseDC ( hwnd , hdc) ; //删除窗体设备内容句柄
          return 0 ;

     case WM_PAINT:
          hdc = BeginPaint ( hwnd , &ps) ;
          //当显示区域重绘时,用内存设备内容中的位图来更新
          //这一设置与鼠标捕获结合时,可以在窗口以外屏幕之内作画,通过拉伸窗口来显示隐藏的数据
          BitBlt ( hdc , 0 , 0 , cxClient , cyClient , hdcMem , 0 , 0 , SRCCOPY) ;

          EndPaint ( hwnd , &ps) ;
          return 0 ;

     case WM_DESTROY:
          //释放内存设备内容和建立的位图
          DeleteDC ( hdcMem) ;
          DeleteObject ( hBitmap) ;
          PostQuitMessage ( 0) ;
          return 0 ;
     }
     return DefWindowProc ( hwnd , message , wParam , lParam) ;
}

你可能感兴趣的:(Windows程序设计 HELLOBIT.C -- SKETCH.C 范例分析笔记)