`
uslt43uslt
  • 浏览: 12083 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

Windows编程学习自己的笔记备份

阅读更多

Windows编程学习自己的笔记备份
2010年10月20日
  LP表示长指针,sz以零结束的字符串,lpfn前缀代表指向函数的长指标
  #include
  WINDOWS.H是主要的含入文件,它包含了其它Windows表头文件,这些表头文件的某些也包含了其它表头文件。这些表头文件中最重要的和最基本的是:
  WINDEF.H 基本型态定义。
  WINNT.H 支持Unicode的型态定义。
  WINBASE.H Kernel函数。
  WINUSER.H 使用者接口函数。
  WINGDI.H 图形设备接口函数。
  #pragma comment(lib,”wsock32.lib”)
  静态调用链接库,在编译时加载
  PARAM参数
  Windows为了消除各编译器的差别,重新定义了一些数据类型。CHAR为单字节字符。还有个WCHAR为Unicode字符,即不论中英文,每个字有两个字节组成。如果当前编译方式为ANSI(默认)方式,TCHAR等价于CHAR,如果为Unicode方式,TCHAR等价于WCHAR。
  LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
  windows是以消息为基础,事件为驱动而运行的
  也就是说,一个事件发生后,windows会产生一个消息,传递给指定的窗口进行处理,既然这样,必须有借口给系统来调用,这个LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM)中第1个参数,是消息要传递的窗口,参数2是消息的id(也就是这是个什么样的消息,比如鼠标左键按下对应的消息是WM_LBUTTONDOWN),参数3和参数4是消息的具体内容
  参数wParam表明窗口是非最小化还是非最大化,是最小化、最大化,还是隐藏。
  lParam参数包含了新窗口的大小,新宽度和新高度均为16位值,合在一起成为32位的lParam。
  前缀    类别
  CS 窗口类别样式
  CW 建立窗口
  DT 绘制文字
  IDI 图示ID
  IDC 游标ID
  MB 消息框
  SND 声音
  WM 窗口消息
  WS 窗口样式
  结构   含义
  MSG 消息结构
  WNDCLASS 窗口类别结构
  PAINTSTRUCT 绘图结构
  RECT    矩形结构
  句柄简介
  最后,还有三个大写标识符(见表3-3),用于不同型态的「句柄」:
  表3-3
  标识符    含义
  HINSTANCE  执行实体(程序自身)句柄
  HWND       窗口句柄
  HDC        设备内容句柄
  匈牙利命名法:许多Windows程序写作者使用一种叫做「匈牙利表示法」的变量命名通则。这是为了纪念传奇性的Microsoft程序写作者Charles Simonyi。非常简单,变量名以一个或者多个小写字母开始,这些字母表示变量的数据型态。在命名结构变量时,可以用结构名(或者结构名的一种缩写)的小写作为变量名的前缀,或者用作整个变量名。
  前缀    数据型态
  c char或WCHAR或TCHAR
  by BYTE (无正负号字符)
  n short
  i int
  x, y int分别用作x坐标和y坐标
  cx, cy int分别用作x长度和y长度;C代表「计数器」
  b或f BOOL (int);f代表「旗标」
  w WORD (无正负号短整数)
  l LONG (长整数)
  dw DWORD (无正负号长整数)
  fn function(函数)
  s string(字符串)
  sz 以字节值0结尾的字符串
  h 句柄
  p 指标
  wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
  wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
  wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);    hbr是handle to brush
  hwnd = CreateWindow (szAppName, // window class name
  TEXT ( "The Hello Program"), // window caption
  WS_OVERLAPPEDWINDOW, // window style
  CW_USEDEFAULT, // initial x position
  CW_USEDEFAULT, // initial y position
  CW_USEDEFAULT, // initial x size
  CW_USEDEFAULT, // initial y size
  NULL, // parent window handle
  NULL, // window menu handle
  hInstance, // program instance handle
  NULL) ; // creation parameters
  每一个windows程序都有一个如下的循环:
  MSG msg;
  while(GetMessage(&msg,null,null,null))
  {
  TranslateMessage(&msg);
  DispatchMessage(&msg);
  }
  消息就是一个的MSG结构,是windows内设的一种数据格式:
  typedef struct{
  HWND hwnd;
  UNIT message;
  WPARAM wParam;
  LPARAM lParam;
  DWORD time;
  POINT pt;}MSG,*PMSG;
  BOOL GetMessage(LPMSG lpMsg,HWND hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax )
  参数: 
  lpMsg:指向MSG结构的指针,该结构从线程的消息队列里接收消息信息。   
  hWnd:取得其消息的窗口的句柄。这是一个有特殊含义的值(NULL)。
  GetMessage为任何属于调用线程的窗口检索消息,线程消息通过PostThreadMessage寄送给调用线程。   
  wMsgFilterMin:指定被检索的最小消息值的整数。   
  wMsgFilterMax:指定被检索的最大消息值的整数。   
  返回值:如果函数取得WM_QUIT之外的其他消息,返回非零值。如果函数取得WM_QUIT消息,返回值是零。如果出现了错误,返回值是-1。例如,当hWnd是无效的窗口句柄或lpMsg是       无效的指针时。若想获得更多的错误信息,请调用GetLastError函数。
  显示窗口的具体步骤:
  1.注册窗口(RegisterClassEX)
  2.创建窗口(CreateWindowEX)
  3.在桌面上显示窗口(ShowWindow)
  4.更新窗口客户区(UpdateWindow)
  5.进入无限的消息获取和处理的循环,首先是获取消息(GetMessage),如果有消息到达,则将消息分派到回调函数处理(DispatchMessage),如果消息是WM_QUIT,则GetMessage函数返回false,整个消息循环结束。
  int DrawText(
    HDC hDC, // 设备描述表句柄
    LPCTSTR lpString, // 将要绘制的字符串
    int nCount, // 字符串的长度
    LPRECT lpRect, // 指向矩形结构RECT的指针
    UINT uFormat // 正文的绘制选项
    );
  该函数在指定的矩形里写入格式化的正文,根据指定的方法对正文格式化(扩展的制表符,字符对齐、折行等)。
  要指定额外的格式化选项,请使用DrawTextEx函数。
  如果nCount为-1,则lpString指向的字符串被认为是以\0结束的,DrawText会自动计算字符数
  TextOut (hdc, x, y, psText, iLength) ;
  psText参数是指向字符串的指针,iLength是字符串中字符的个数。如果psText指向Unicode字符串,则字符串中的字节数就是iLength值的两倍。字符串中不能包含任何ASCII控制字符(如回车、换行、制表或退格),Windows会将这些控制字符显示为实心块。Text0ut不识别作为字符串结束标志的内容为零的字节(对于Unicode,是一个短整数型态的0),而需要由nLength参数指明长度。
  每个窗口会有一个称为窗口过程的回调函数(WndProc),它带有四个参数,分别为:窗口句柄(Window Handle),消息ID(Message ID),和两个消息参数(wParam, lParam)
  在处理WM_PAINT消息时,使用这种方法。它涉及BeginPaint和EndPaint两个函数,这两个函数需要窗口句柄(作为参数传给窗口消息处理程序)和PAINTSTRUCT结构的变量(在WINUSER.H表头文件中定义)的地址为参数。Windows程序写作者通常把这一结构变量命名为ps并且在窗口消息处理程序中定义它:
  PAINTSTRUCT ps ;
  在处理WM_PAINT消息时,窗口消息处理程序首先呼叫BeginPaint。BeginPaint函数一般在准备绘制时导致无效区域的背景被擦除。该函数也填入ps结构的字段。BeginPaint传回的值是设备内容句柄,这一传回值通常被保存在叫做hdc的变量中。它在窗口消息处理程序中的定义如下:
  HDC hdc ;
  HDC数据型态定义为32位的无正负号整数。然后,程序就可以使用需要设备内容句柄的TextOut等GDI函数。呼叫EndPaint即可释放设备内容句柄。
  一般地,处理WM_PAINT消息的形式如下:
  caseWM_PAINT:
  HDC hdc;
  hdc = BeginPaint (hwnd, &ps) ;
  使用GDI函数
  TextOut(hdc, 10, 10, szText,sizeof(szText));
  //DrawText(hdc,TEXT("最简单的窗口程序!"),-1,&rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);   ///如果nCount为-1,则lpString指向的字符串被认为是以\0结束的,DrawText会自动计算字符数
  EndPaint (hwnd, &ps) ;
  return 0;
  在处理WM_PAINT消息时,必须成对地呼叫BeginPaint和EndPaint。如果窗口消息处理程序不处理WM_PAINT消息,则它必须将WM_PAINT消息传递给Windows中DefWindowProc(内定窗口消息处理程序)。DefWindowProc以下列代码处理WM_PAINT消息:
  case WM_PAINT:
  BeginPaint (hwnd, &ps) ;
  EndPaint (hwnd, &ps) ;
  return 0 ;
  这两个BeginPaint和EndPaint呼叫之间中没有任何叙述,仅仅使先前无效区域变为有效。但以下方法是错误的:
  case WM_PAINT:
  return 0 ; // WRONG !!!
  Windows将一个WM_PAINT消息放到消息队列中,是因为显示区域的一部分无效。如果不呼叫BeginPaint和EndPaint(或者ValidateRect),则Windows不会使该区域变为有效。相反,Windows将发送另一个WM_PAINT消息,且一直发送下去。
  wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
  在处理WM_PAINT消息时,为了在更新的矩形外绘图,可以使用如下呼叫:
  InvalidateRect (hwnd, NULL, TRUE) ;
  该呼叫在BeginPaint呼叫之前进行,它使整个显示区域变为无效,并擦除背景。但是,如果最后一个参数等于FALSE,则不擦除背景,原有的东西将保留在原处。
  虽然最好是在处理WM_PAINT消息处理期间更新整个显示区域,但是您也会发现在处理非WM_PAINT消息处理期间绘制显示区域的某个部分也是非常有用的。或者您需要将设备内容句柄用于其它目的,如取得设备内容的信息。
  要得到窗口显示区域的设备内容句柄,可以呼叫GetDC来取得句柄,在使用完后呼叫ReleaseDC:
  hdc = GetDC (hwnd) ;
  使用GDI函数
  ReleaseDC (hwnd, hdc) ;
  与BeginPaint和EndPaint一样,GetDC和ReleaseDC函数必须成对地使用
  与从BeginPaint传回设备内容句柄不同,GetDC传回的设备内容句柄具有一个剪取矩形,它等于整个显示区域。可以在显示区域的某一部分绘图,而不只是在无效矩形上绘图(如果确实存在无效矩形)。与BeginPaint不同,GetDC不会使任何无效区域变为有效。如果需要使整个显示区域有效,可以呼叫
  ValidateRect (hwnd, NULL) ;
  一般可以呼叫GetDC和ReleaseDC来对键盘消息(如在字处理程序中)和鼠标消息(如在画图程序中)作出反应
  显示简单窗口:
  ////////////////////
  ///////////////////
  ///////////////////
  #include
  LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
  int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
  {
  WNDCLASS wndclass;
  TCHAR szClassName[] = TEXT("HELLO WORLD!");
  wndclass.cbClsExtra = 0;
  wndclass.cbWndExtra = 0;
  wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
  wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
  wndclass.hInstance = hInstance;
  wndclass.lpfnWndProc = WndProc;
  wndclass.lpszClassName = szClassName;
  wndclass.lpszMenuName = NULL;
  wndclass.style = CS_VREDRAW | CS_HREDRAW;
  RegisterClass(&wndclass);
  HWND hwnd;
  hwnd = CreateWindow(
  szClassName,
  TEXT("Hello World!"),
  WS_OVERLAPPEDWINDOW,
  CW_USEDEFAULT,
  CW_USEDEFAULT,
  CW_USEDEFAULT,
  CW_USEDEFAULT,
  NULL,
  NULL,
  hInstance,
  NULL);
  if (hwnd == NULL)
  {
  MessageBox(NULL,TEXT("窗口创建失败!"),TEXT("ERROR!"),MB_OK);
  return -1;
  }
  ShowWindow(hwnd,nShowCmd);
  UpdateWindow(hwnd);
  MSG msg;
  while(GetMessage(&msg,hwnd,0,0))
  {
  TranslateMessage(&msg);
  DispatchMessage(&msg);
  }
  return msg.wParam;
  }
  LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
  {
  TCHAR szCharText[] = TEXT("窗前明月光!");
  switch (message)
  {
  case WM_PAINT:
  HDC hdc;
  PAINTSTRUCT ps;
  RECT rect;
  GetClientRect(hwnd,&rect);
  hdc = BeginPaint(hwnd,&ps);
  DrawText(hdc,szCharText,-1,&rect,DT_SINGLELINE|DT_VCENTER|DT_CENTER);
  //TextOut(hdc,20,20,szCharText,sizeof(szCharText));    //两种显示方式 可以通过SetTextColor(hdc,RGB(255,0,0));SetTextAlign(hdc,TA_BOTTOM);
  EndPaint(hwnd,&ps);
  return 0;
  case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
  }
  return DefWindowProc(hwnd,message,wParam,lParam);
  }
  //////////////////
  /////////////////
  /////////////////
  ////////////////
  我在第二章讲到过,您不能使惯用的工具(可爱的printf函数)来完成这项工作,但是可以使用sprintf和Windows版的sprintf-wsprintf。这些函数与printf相似,只是把格式化字符串放到字符串中。然后,可以用TextOut将字符串输出到显示器上。非常方便的是,从sprintf和wsprintf传回的值就是字符串的长度。您可以将这个值传递给TextOut作为iLength参数。下面的程序代码显示了wsprintf与TextOut的典型组合:
  int iLength ;
  TCHAR szBuffer [40] ;
  iLength = wsprintf (szBuffer, TEXT ("The sum of %i and %i is %i"),
  iA, iB, iA + iB) ;
  TextOut (hdc, x, y, szBuffer, iLength) ;
  对于这样简单的情况,可以将nLength的定义值与TextOut放在同一条叙述中,从而无需定义iLength:
  TextOut (hdc, x, y, szBuffer,
  wsprintf (szBuffer, TEXT ("The sum of %i and %i is %i"),
  iA, iB, iA + iB)) ;
  我们使用GetClientRect函数来取得显示区域的大小。使用这个函数没有什么不好,但是在您每次要使用信息时就去呼叫它一遍是没有效率的。确定窗口显示区域大小的更好方法是在窗口消息处理程序中处理WM_SIZE消息。在窗口大小改变时,Windows给窗口消息处理程序发送一个WM_SIZE消息。传给窗口消息处理程序的lParam参数的低字组中包含显示区域的宽度,高字组中包含显示区域的高度。要保存这些尺寸,需要在窗口消息处理程序中定义两个静态变量:
  static int cxClient, cyClient ;
  与cxChar和cyChar相似,这两个变量在窗口消息处理程序内定义为静态变量,因为在以后处理其它消息时会用到它们。处理WM_SIZE的方法如下:
  caseWM_SIZE:
  cxClient = LOWORD (lParam) ;
  cyClient = HIWORD (lParam) ; ////这个参数是32位的高16位存储的是宽度,低16位存储的是高度
  return 0 ;
  在许多Windows程序中,WM_SIZE消息必然跟着一个WM_PAINT消息
  很容易在应用程序中包含水平或者垂直的滚动条,程序写作者只需要在CreateWindow的第三个参数中包括窗口样式(WS)标识符WS_VSCROLL(垂直卷动)和/或WS_HSCROLL(水平卷动)即可。
  SetScrollRange (hwnd, iBar, iMin, iMax, bRedraw) ;
  参数iBar为SB_VERT或者SB_HORZ,iMin和iMax分别是范围的最小值和最大值。如果想要Windows根据新范围重画滚动条,则设置bRedraw为TRUE(如果在呼叫SetScrollRange后,呼叫了影响滚动条位置的其它函数,则应该将bRedraw设定为FALSE以避免过多的重画)。
  您可以使用SetScrollPos在滚动条范围内设置新的卷动方块位置:
  SetScrollPos (hwnd, iBar, iPos, bRedraw) ;
  参数iPos是新位置,它必须在iMin至iMax的范围内。Windows提供了类似的函数(GetScrollRange和GetScrollPos)来取得滚动条的目前范围和位置。
  /////////////////////////////
  //////////////////////////////
  //////////////////////////////
  ///////////////////////////////
  ////////////////////////////////
  /////////////////////////////////
  MFC:
  四个基本类:
  应用程序类 CMyApp
  框架窗口类 CMyWnd
  视图类CMyView,该类定义如何在CMyWnd对象创建的窗口的客户区中显示CMyDoc对象包含的数据
  文档类CMyDoc,该类定义包含应用程序数据的文档
  CAboutDlg类,该类定义的对象用来支持用户在应用程序中选择Help|About菜单项时出现的对话框
  创建MFC程序时的选项含义:
  Dialog based        应用程序窗口是对话框窗口,不是框架窗口
  Multiple top-level Documents       文档显示在桌面的子窗口中,而非像MDI应用程序中那样显示在应用窗口的子窗口中
  Document/View architecture support  该选项默认是选中的,因此我们会得到内置的支持文档/视图体系结构的代码。如果我们取消对改选项的选中,则得不到这样的支持,而如                                    何实现所需的功能将由编程人员负责
  Resource language  该下拉列表框显示出适用于程序中像菜单和文本串这样的资源的可用语言选项
  Use Unicode libraries 借助MFC库的Unicode版本,提供对Unicoede的支持;如果需要使用Unicode版本,则必须选中该选项
  在Document Template Strings对话框中,输入的文件扩展名就是要在open或者save as对话框中出现的过滤器的名称,可以对文件列表进行过滤,使列表中只显示那些指定扩展名的文件
  User Interface Features选项:
  Thick Frame 该选项使我们可以拖动应用程序窗口的变框调整窗口的大小。该选项是默认选中的。
  Minimize box 该选项默认也是选中的,用来在应用程序窗口的右上角提供最小化按钮
  Maximize box 该选项默认也是选中的,用来在应用程序窗口的右上角提供最大化按钮
  Minimzed     如果我们选中该项,则应用程序开始时其窗口是最小化的,因此是以图标的形式出现
  Maximized    如果我们选中该项,则应用程序开始时其窗口是最大化的
  Initial status bar 该选项在应用程序窗口的底部添加一个状态栏,其中包括CAPS LOCK,NUM LOCK和SCROLL LOCK键的状态指示,还有一个消息行用来显示菜单和工具栏按钮的帮助信息。该选项同时会添加隐藏或显示状态栏的菜单命令
  Split window  改选项为每个应用程序主视图提供分隔条
  Standard docking toolbar 该选项给应用程序添加一组标准按钮的工具栏,这些按钮可以替代标准菜单项的使用。工具栏默认提供。可停靠的工具栏可以拖到应用程序的两边或者底部,因此可以将其放在最方便的位置。
  Browser style toolbar  该选项给应用程序窗口添加一个Internet Explorer
  Generated Class选项
  CEditView  提供简单的多行文本编辑功能------包括查找和替换,打印
  CFormView  提供表单视图;表单是一种对话框,可以包含提供数据显示和用户输入等功能的控件。
  CHtmlEditView 该类扩充了CHtmlView类,添加了编辑HTML页面的功能。
  CHtmlView  提供可以显示Web页面和本地HTML文档的视图
  CListView  使我们能够以列表控件的形式使用文档-视图体系结构
  CRichEditView 提供显示和编辑包含丰富编辑文本文档的功能
  CScrollView 提供可以在显示的数据需要时自动添加滚动条的视图
  CTreeView   提供以树形控件形式使用文档-视图体系结构的功能
  CView       提供查看文档的基本功能
  #pragma once(比较常用)
  这是一个比较常用的指令,只要在头文件的最开始加入这条指令就能够保证头文件被编译一次
  #pragma once用来防止某个头文件被多次include,#ifndef,#define,#endif用来防止某个宏被多次定义。
  #pragma once是编译相关,就是说这个编译系统上能用,但在其他编译系统不一定可以,也就是说移植性差,不过现在基本上已经是每个编译器都有这个定义了。
  #ifndef,#define,#endif这个是C++语言相关,这是C++语言中的宏定义,通过宏定义避免文件多次编译。所以在所有支持C++语言的编译器上都是有效的,如果写的程序要跨平台,最好使用这种方式
  类的消息映射仅仅是处理windows消息的成员函数表。消息映射中的每一项都将一个函数和一个特定的消息关联起来;在出现给定的消息是,将调用对应的函数,只有与一个类有关的消息才能出现在该类的消息映射中
  类的消息映射是在创建一个项目时,由MFC Application Wizard自动创建的,或者是在把处理消息的类添加到程序中时由ClassWizard创建的。对消息映射的添加和删除主要是由ClassWizard管理的,但是有时候需要手动修改消息映射。
  在代码中消息映射的开始有BEGIN_MESSAGE_MAP()宏表示,消息的映射的结束由END_MESSAGE-MAP()宏表示。
  afx_msg void OnAppAbout();   afx_msg这个单词区分消息处理程序和类中的其他成员
  DECLARE_MESSAGE_MAP();       这个宏表明这个类包含作为消息处理程序的函数成员
  如果要把自己的成员直接添加到一个类中,最好最好是把DECLARE_MESSAGE_MAP()宏作为最后一行放到类中定义。如果确实要在DECLARE_MESSAGE_MAP()宏之后添加成员,还需要包括这些成员的访问说明符:公有,受保护或者私有
  BEGIN_MESSAGE_MAP(CSketcherApp, CWinApp)
  ON_COMMAND(ID_APP_ABOUT, &CSketcherApp::OnAppAbout)
  // 基于文件的标准文档命令
  ON_COMMAND(ID_FILE_NEW, &CWinApp::OnFileNew)
  ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)
  // 标准打印设置命令
  ON_COMMAND(ID_FILE_PRINT_SETUP, &CWinApp::OnFilePrintSetup)
  END_MESSAGE_MAP()
  消息映射通过消息中的标识符(ID)了解按下哪个菜单或键。在前面的代码中有四个宏,每个要被处理的命令消息都有一个宏。这种宏的第一个参数是一个与特定命令相关联的ID,ON_COMMAND宏将函数名和这个ID指定的命令联系起来。因此,在接收到一个对应标识符ID_APP_ABOUT的消息时,将调用OnAppAbout()函数。
  BEGIN_MESSAGE_MAP()宏有两个参数。第一个参数标识为其定义短消息映射的当前类型,第二个参数提供一个到该基类的连接,以查找消息处理程序。如果在定义消息映射的类中没有发现处理程序,那么将搜索基类的消息映射。
  注意在手工添加消息处理程序时不应当把一个消息(如果是命令消息,则是命令ID)映射到类中的多个消息处理程序上。如果这样做,它不会破坏任何东西,但是第二个消息处理程序永远不会被调用。通常可以通过属性窗口添加消息处理程序,这时不能将一个消息映射到一个以上的消息处理程序上。
  不能把一个消息处理程序放在您喜欢的任何地方。放置处理程序的许可位置取决于要处理的消息的类别
  对于标准Windows消息来说,CWnd类提供了默认的消息处理方法。因此,如果派生类没有包括标准windows消息的处理程序,那么在这个基类中定义的默认处理程序将进行处理。
  如何处理命令消息:
  所有命令消息都将发送到应用程序的主框架窗口,然后主框架窗口将按照一个特定的顺序把这个消息传送给程序中的类,如果一个类不能处理这个消息,它将把这个消息传递给下一类。如果所有的类都没定义处理程序,那么默认的windows处理方法将处理这个消息,基本上市丢弃它。
  对于SDI程序来说,类处理消息的顺序是:
  1.视图对象
  2.文档对象
  3.文档模板对象
  4.主框架窗口对象
  5.应用程序对象
  对于MDI程序来说,情况稍微有点复杂。虽然您可能有多个文档,每个文档有多个视图,但是只有活动视图及其关联文档才能参与命令消息的传送。在MDI程序中,传送命令消息的顺序是:
  1.活动视图对象
  2.与活动视图相关联的文档对象
  3.活动文档的文档模板对象
  4.活动视图的框架框架窗口对象
  5.主框架窗口对象
  6.应用程序对象
  MFC使用IDR_前缀标识为窗口定义完整菜单的资源
  如果在一个菜单项中一个字母的前面输入符号&,那么这个字母将被标识为从键盘调用这个菜单的快捷键。第一个菜单项E&lement。这将把l选作快捷键字母,所以按下Alt+l,即可调用这个菜单项。
  没有ID对于一个弹出式菜单是必要的。因为选择它之后将只在下面显示这个菜单,并且没有需要代码处理的事件。
  在处理菜单项时,每种消息适合于不同的目的:
  COMMAND  在选择了特定的菜单项时将发出这种消息。处理程序应当提供适合于所选菜单项的动作,例如,设置文档对象中的当前颜色,或者设置元素类型
  UPDATE_COMMAND_UI  取决于菜单的状态,在应当更新------例如复选或者未选中---------菜单时将发出这种消息。这种消息出现在显示菜单之前,所以您可以在用户看到这个菜单项外观之前进行设置。
  当您想在一个图形输出设备(诸如屏幕或者打印机)上绘图时,您首先必须获得一个设备内容(或者DC)的句柄。将句柄传回给程序时,Windows就给了您使用设备的权限。然后您在GDI函数中将这个句柄作为一个参数,向Windows标识您想在其上进行绘图的设备。
  如果您需要目前位置,就可以通过以下呼叫获得:
  GetCurrentPositionEx (hdc, &pt) ;
  其中,pt是POINT结构的。
  Windows GDI 设备环境中的每种映射模式都有一个ID标识,其方式与标识Windows消息时类似。每个符号都有一个前缀MM_,表明它将定义映射模式。Windows提供的映射模式如表所示
  MM_TEXT    逻辑单位是一个设备像素,在窗口客户区中,x轴的正方向从左到右,y轴的正方向从上到下。
  MM_LOENGLISH   逻辑单位是0.01英寸,x轴的正方向从左到右,y轴的正方向从客户区的顶部向上延伸。
  MM_HIENGLISH   逻辑单位是0.001英寸,x轴和y轴的方向与MM_LOENGLISH相同
  MM_LOMETRIC    逻辑单位是0.1毫米,x轴和y轴的方向和MM_LOENGLISH相同
  MM_HIMETRIC    逻辑单位是0.01毫米,x轴和y轴的方向与MM_LOENGLISH相同
  MM_ISOTROPIC   逻辑单位是任意长度,但是在x轴和y轴上是相同的。x轴和y轴的方向与MM_LOENGLISH相同
  MM_ANISOTROPIC 这种模式类似于MM_ISOTROPIC,但是它准许x轴上逻辑单位的长度不同于y轴上的逻辑单位的长度
  MM_TWIPS       逻辑单位是TWIP,其中的TWIP是一个点的0.05,而一个点是1/72英寸。所以TWIP相当于1/1440英寸,即6.9x10(-4)英寸。(点是衡量字体的单位)。x轴和y轴的方               向与MM_LOENGLISH相同
  MM_TEXT是设备环境的默认映射模式。如果需要使用一种不同的映射模式,就必须设法修改它。默认情况下,在每种映射模式中,位于客户区左上角的坐标都是(0,0),但是如果需要的话,也可以把原点移动到客户区左上角以外的位置。
  以像素为单位绘制的图形会随着显示器的分辨率的调整而大小改变,以毫米或者英寸为单位的不会改变。
  每当需要从新绘制文档窗口的客户区时或者当程序收到WM_PAINT消息时,都要调用OnDraw()函数
  void CSketcherView::OnDraw(CDC* pDC)   //参数pDC的名称代表pointer to Device Context
  {
  CSketcherDoc* pDoc = GetDocument();
  ASSERT_VALID(pDoc);   //确保指针pDoc包含有效的地址
  if (!pDoc)            //确保pDoc不是空的
  return;
  }
  因为将使用这些代码在OnDraw()成员函数中绘制文档,所以Application Wizard已经包括了指针pDoc的声明,并且使用函数GetDocument()对这个指针进行了初始化,函数GetDocument()将返回与当前视图有关的文档对象的地址:CSketcherDoc* pDoc = GetDocument();
  函数GetDocument()实际上将从m_pDocument检索指向文档的指针,m_pDocument是视图对象的继承的数据成员。这个函数将进行重要的任务,就是把存储在这个数据成员中的指针强制转换成对应于应用程序中文档类型CSketcherDoc的类型。这样,编译器就可以访问已经定义的文档类型的成员;否则,编译器只能够访问基类的成员。因此,pDoc将指向应用程序中与当前视图关联的文档对象,当需要绘制这个文档对象时,可以使用这个指针访问存储在这个文档对象中的数据。
  CDC类将重载MoveTo()函数,这样就可以灵活地指定想要设置为当前位置的位置。MoveTo函数有两个版本,它们在CDC类中被声明为:
  CPoint MoveTo(int x,int y);  //Move to position x,y
  CPoint MoveTo(POINT aPoint); //Move to position defined by aPoint
  第一个版本接受作为独立参数的x和y坐标。第二个版本接受一个POINT类型的参数,它是一个具有如下定义的结构:
  typedef struct tagPOINT
  {
  LONG x;
  LONG y;
  } POINT;
  其中的坐标是struct的成员,类型为LONG(这种类型在Windows API中定义,对应于32位有符号整数)。您可能喜欢使用类,而不喜欢使用结构,这时可以在能够使用POINT对象的地方使用CPoint类的对象。CPoint类具有LONG类型的数据成员x和y,使用CPiont对象的优点在于这个类还定义了对CPoint和POINT对象进行操作的成员函数。MoveTo函数的返回值是一个CPonit对象,它存储的是移动之前的位置,用于再次移动会原来的位置
  在对OnDraw()函数中的MoveTo()调用以后,调用函数LineTo(),这将在客户区中绘制一条直线,它从当前位置到LineTo()函数的参数指定的位置。
  BOOL LineTo(int x,int y);  //Draw a line to position x,y
  BOOL LineTo(POINT aPoint);  //Draw a line to position defined by aPoint
  在执行LineTo()函数时,当前位置将变成这条直线末端指定的点
  pDC->MoveTo(50,50);
  pDC->LineTo(50,200);
  pDC->LineTo(150,200);
  pDC->LineTo(150,50);
  pDC->LineTo(50,50); ///////////绘制一个矩形
  用Polyline函数画正弦函数:
  #define NUM 1000
  #define TWOPI (2 * 3.14159)
  LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  {
  static int cxClient, cyClient ;
  HDC hdc ;
  int i ;
  PAINTSTRUCT ps ;
  POINT apt [NUM] ;
  switch (message)
  {
  case WM_SIZE:
  cxClient = LOWORD (lParam) ;
  cyClient = HIWORD (lParam) ;
  return 0 ;
  case WM_PAINT:
  hdc = BeginPaint (hwnd, &ps) ;
  MoveToEx (hdc, 0, cyClient / 2, NULL) ;
  LineTo (hdc, cxClient, cyClient / 2) ;
  for (i = 1 ; i wParam, lParam) ;
  }
  画矩形最简单函数Rectangle (hdc, xLeft, yTop, xRight, yBottom);
  点(xLeft, yTop)是矩形的左上角,(xRight, yBottom)是矩形的右下角。,Rectangle严格地说不是画线函数,GDI也填入封闭区域。然而,因为内定用白色填入区域,因此GDI填入区域并不明显
  画椭圆函数Ellipse (hdc, xLeft, yTop, xRight, yBottom) ;//这个参数的意义和Rectangle函数参数的意义是一样的
  画圆角矩形的函数使用与函数Rectangle及Ellipse函数相同的边界框,还包含另外两个参数:
  RoundRect (hdc, xLeft, yTop, xRight, yBottom,xCornerEllipse, yCornerEllipse) ;
  Windows使用一个小椭圆来画圆角,这个椭圆的宽为xCornerEllipse,高为yCornerEllipse。可以想象这个小椭圆分为了四个部分,一个象限一个,每个刚好用在矩形的一个角上。xCornerEllipse和yCornerEllipse的值越大,角就越明显。如果xCornerEllipse等于xLeft与xRight的差,且yCornerEllipse等于yTop与yBottom的差,那么RoundRect函数将画出一个椭圆。
  Arc、Chord和Pie函数都只要相同的参数:
  Arc(hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd) ;
  Chord (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd) ;
  Pie(hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd) ;
  对于Arc函数,这样就结束了。因为弧只是一条椭圆形的线而已,而不是一个填入区域。对于Chord函数,Windows连接弧线的端点。而对于Pie函数,Windows将弧的两个端点与椭圆的中心相连接。弦与扇形图的内部以目前画刷填入。
  绘制园:
  绘制不进行填充的园的另一种方法是适应Arc()函数,它不涉及画刷。其优点是可以绘制椭圆的任意一段弧,而不是完整的曲线。这个函数在CDC类中有两个版本,它们的声明如下所示:
  BOOL Arc(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4);
  BOOL Arc(LPCRECT lpRect,POINT StartPt,POINT EndPt);
  在第一个版本中,(x1,y1)和(x2,y2)定义包围整个曲线的矩形的左上角和右上角,如果把这些坐标变成正方形的角,那么绘制的曲线就是园的一段。点(x3,y3)和(x4,y4)定义这段曲线的起点和终点。这段曲线是按逆时针方向绘制的。如果使(x3,y3)和(x4,y4)相等,那么将生成一个完整的,闭合的曲线。
  void CSketcherView::OnDraw(CDC* pDC)   //参数pDC的名称代表pointer to Device Context
  {
  CSketcherDoc* pDoc = GetDocument();
  ASSERT_VALID(pDoc);   //确保指针pDoc包含有效的地址
  if (!pDoc)            //确保pDoc不是空的
  return;
  CPen apen; //创建一个画笔
  apen.CreatePen(PS_SOLID,2,RGB(255,0,0)); ////初始化这个画笔
  CPen* pOldPen = pDC->SelectObject(&apen); /////保留以前的画笔
  pDC->Arc(50,150,250,250,50,50,50,50);
  CRect* pRect = new CRect(250,50,300,100);
  CPoint Start(275,100);
  CPoint End(250,75);
  pDC->Arc(pRect,Start,End);
  delete pRect;
  pDC->SelectObject(pOldPen);    /////回复以前的画笔
  }
  在定义边界矩形时,使用的是CRect类对象,而不是RECT结构,另外还使用了CPoint类对象,而没有使用POINT结构。
  创建画笔: CPen aPen;
  初始化:   BOOL CreatPen(int aPenstyle, int aWidth,COLORREF aColor);  
  画笔的线型:
  PS_SOLID       绘制实线
  PS_DASH        绘制虚线,只有在把画笔宽度指定为1时,这种线型才有效
  PS_DOT         绘制点线,只有在把画笔宽度指定为1时,这种线型才有效
  PS_DASHDOT     绘制一划一点相间的直线。只有在把画笔宽度指定为1时,这种线型才有效
  PS_DASHDOTDOT  绘制一划双点相间的直线。只有在把画笔宽度指定为1时,这种线型才有效
  PS_NULL        不进行任何绘制
  PS_INSIDEFRAME 绘制实线,但是和PS_SOLID不同,指定实线的点出现在画笔的边缘而不是中心,所以绘制的对象永远不会超出封闭矩形
分享到:
评论

相关推荐

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 第一章 Oracle入门 一、 数据库概述 数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,它产生于距今五十年前。简单来说是本身可视...

    【最新版】FSNotes_4.5.6.zip【亲测可用】最好的现代Notes管理器

    支持170多种编程语言。 在线图像支持。 使用标签进行组织。 跨笔记链接使用[[double brackets]]。 弹性两窗格视图。选择垂直或水平布局。 外部编辑器支持(更改与UI的无缝实时同步)。 固定重要的笔记。 快速将笔记...

    jotz:程序员的终极笔记本

    该应用程序还与 Github 集成,用于备份您的笔记和发布要点。 JotZ 是用 Javascript、HTML 和 SASS 编写的,使用 (以前称为 Atom-Shell)、 、 和 。 下载 在获取适用于 Mac 和 Windows 的应用程序 发展 JotZ 是...

    电脑开机logo修改软件加刷bios工具包支持8_9_10_11_12代主板v3.0

    电脑开机logo修改软件加刷bios...免编程器刷bios软件和改bios logo图片软件合集 支持12代电脑,11代电脑,10代电脑,9代电脑,8代电脑主板 直接在windows电脑上操作,非常方便。 个性化设置电脑开机图案图片logo软件

    广州凯恒BIOS烧写王

    4.进入WINDOWS操作系统 5.打开编程软件,如杀毒软件报毒请将杀毒软件关闭或者将编程软件加入信任 6.请查看软件右下角并口号(LPT号)与计算机所连并口号是否相同,计算机并口号见设备管理器 7.点击菜单栏“帮助...

    JavaScript实现的Git项目JS-Git.zip

    Windows RT WinJS App HTML5 Web App(在所有现代浏览器上,包括IE 10) PhoneGap App 桌面Chrome App 以及其它在JavaScript里支持网络访问、持久存储和二进制的应用 功能目标 项目开发者并不打算完全...

    学生成绩管理系统需求规格说明书(教学用例)

    由于时间比较短,使用计算机不方便以及对于网络编程不是很熟悉,因此本学生成绩管理系统并没有提供数据的远程访问功能。对于信息的保护手段仅限于设置用户级别,以及提供数据文件的备份,比较简单,安全性能有待...

    高性能动态SQL Oracle数据安全 Oracle 数据库的聚簇技术 等等

    用Windows脚本宿主自动化Oracle工具 31 进程结构和内存结构 32 Oracle监控数据库性能的SQL汇总 36 Oracle如何精确计算row的大小 38 PL/SQL编程 39 数据库的分组问题 41 oracle知识 42 数据库的导入导出 42 Oracle...

    vc源代码合集0951.rar

    2012-06-12 11:57 182 Visual C++技术内幕摘要笔记.rar 2012-06-12 11:50 3,620,678 visual c++网络通信编程实用案例精选(源代码).rar 2012-06-12 12:23 3,982,016 Visual_C++网络编程经典案例详解PPT.rar 2012-06-...

    《电脑爱好者》2011年笫15期

     特别话题Ⅰ:每期一个话题,围绕着各种非硬件技巧进行话题,通常是引用一个真实的小故事改编为主线来讲述,如“备份”,“Windows 7"等。版块栏目2 系统:围绕着电脑操作系统来讲述一些窍门和知识,如“修复系统...

    《电脑爱好者》2011年14期

     特别话题Ⅰ:每期一个话题,围绕着各种非硬件技巧进行话题,通常是引用一个真实的小故事改编为主线来讲述,如“备份”,“Windows 7"等。版块栏目2 系统:围绕着电脑操作系统来讲述一些窍门和知识,如“修复系统...

    《电脑爱好者》2011年10期

     特别话题Ⅰ:每期一个话题,围绕着各种非硬件技巧进行话题,通常是引用一个真实的小故事改编为主线来讲述,如“备份”,“Windows 7"等。版块栏目2 系统:围绕着电脑操作系统来讲述一些窍门和知识,如“修复系统...

    《电脑爱好者》2011年11期

     特别话题Ⅰ:每期一个话题,围绕着各种非硬件技巧进行话题,通常是引用一个真实的小故事改编为主线来讲述,如“备份”,“Windows 7"等。版块栏目2 系统:围绕着电脑操作系统来讲述一些窍门和知识,如“修复系统...

    《电脑爱好者》2011年第6期

     特别话题Ⅰ:每期一个话题,围绕着各种非硬件技巧进行话题,通常是引用一个真实的小故事改编为主线来讲述,如“备份”,“Windows 7"等。版块栏目2 系统:围绕着电脑操作系统来讲述一些窍门和知识,如“修复系统...

    《电脑爱好者》2011年第1期1月上

     特别话题Ⅰ:每期一个话题,围绕着各种非硬件技巧进行话题,通常是引用一个真实的小故事改编为主线来讲述,如“备份”,“Windows 7"等。版块栏目2 系统:围绕着电脑操作系统来讲述一些窍门和知识,如“修复系统...

    电脑爱好者2011年笫8期

     特别话题Ⅰ:每期一个话题,围绕着各种非硬件技巧进行话题,通常是引用一个真实的小故事改编为主线来讲述,如“备份”,“Windows 7"等。版块栏目2 系统:围绕着电脑操作系统来讲述一些窍门和知识,如“修复系统...

    《电脑爱好者》2011年第2期1月下

     特别话题Ⅰ:每期一个话题,围绕着各种非硬件技巧进行话题,通常是引用一个真实的小故事改编为主线来讲述,如“备份”,“Windows 7"等。版块栏目2 系统:围绕着电脑操作系统来讲述一些窍门和知识,如“修复系统...

    《电脑爱好者》2011年第3期

     特别话题Ⅰ:每期一个话题,围绕着各种非硬件技巧进行话题,通常是引用一个真实的小故事改编为主线来讲述,如“备份”,“Windows 7"等。版块栏目2 系统:围绕着电脑操作系统来讲述一些窍门和知识,如“修复系统...

    《电脑爱好者》2011年第5期

     特别话题Ⅰ:每期一个话题,围绕着各种非硬件技巧进行话题,通常是引用一个真实的小故事改编为主线来讲述,如“备份”,“Windows 7"等。版块栏目2 系统:围绕着电脑操作系统来讲述一些窍门和知识,如“修复系统...

    《电脑爱好者》2011年12期

     特别话题Ⅰ:每期一个话题,围绕着各种非硬件技巧进行话题,通常是引用一个真实的小故事改编为主线来讲述,如“备份”,“Windows 7"等。版块栏目2 系统:围绕着电脑操作系统来讲述一些窍门和知识,如“修复系统...

Global site tag (gtag.js) - Google Analytics