列表 上一篇 下一篇

译(Making a simple application using the Win32 API)

按Wizard默认生成一个标准的win32程序

修改资源文件、窗口外观

  1. Resource.h添加
#define IDM_ADD 110 #define IDM_SUB 111 #define IDM_MULT 112 #define IDM_REM 113 #define IDC_RHS 114 #define IDC_LHS 115 #define IDC_RESULT 116 #define IDC_OPBUTTON 117

如图:
ID
2. 右键(“Your Project Name”).rc-->查看代码,IDC_CALC MENU下添加

POPUP "计算(&O)" BEGIN MENUITEM "Add" IDM_ADD MENUITEM "Subtract" IDM_SUB MENUITEM "Multiply" IDM_MULT MENUITEM "Remainder" IDM_REM END

如图:
MENU
3. (“Your Project Name”).cpp中
MyRegisterClass()修改窗口背景颜色

wcex.hbrBackground = CreateSolidBrush(RGB(180, 180, 180));

MyRegisterClass()修改窗口大小、样式

hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, 0, 200, 200, NULL, NULL, hInstance, NULL);

向窗口中添加控件((“Your Project Name”).cpp)

  1. 添加WM_CREATE消息处理
case WM_CREATE: CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT("0"), WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL|WS_TABSTOP, 20, 10, 85, 25, hWnd, (HMENU)IDC_LHS, GetModuleHandle(NULL), NULL); CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT("0"), WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL|WS_TABSTOP, 20, 45, 85, 25, hWnd, (HMENU)IDC_RHS, GetModuleHandle(NULL), NULL); CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT("0"), WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL|WS_TABSTOP, 20, 85, 85, 25, hWnd, (HMENU)IDC_RESULT, GetModuleHandle(NULL), NULL); CreateWindowEx(NULL, TEXT("BUTTON"), TEXT("+"), WS_CHILD|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON|WS_TABSTOP, 115, 45, 85, 25, hWnd, (HMENU)IDC_OPBUTTON, GetModuleHandle(NULL), NULL); break;


2. 绘制分割线,修改WM_PAINT消息处理

MoveToEx(hdc, 10, 78, NULL); LineTo(hdc, 115, 78);

如图
WM_PAINT

添加相应函数((“Your Project Name”).cpp)

  1. 添加全局变量
enum operation {ADD,SUB,MULT,REM}; operation op = ADD;

如图
op
2. 添加菜单处理函数

case IDM_ADD: SetDlgItemText(hWnd, IDC_OPBUTTON, TEXT("+")); op = ADD; break; case IDM_SUB: SetDlgItemText(hWnd, IDC_OPBUTTON, TEXT("-")); op = SUB; break; case IDM_MULT: SetDlgItemText(hWnd, IDC_OPBUTTON, TEXT("*")); op = MULT; break; case IDM_REM: SetDlgItemText(hWnd, IDC_OPBUTTON, TEXT("%")); op = REM; break;

如图:
wm_menu
3. 添加运算按钮处理函数,不要忘了case下的第一层大括号

case IDC_OPBUTTON: { BOOL success = false; int lhs = GetDlgItemInt(hWnd, IDC_LHS, &success, true); if(!success){ MessageBox(hWnd, TEXT("the first expression is not an integer。"), TEXT("Error"), MB_OK); break; } int rhs = ::GetDlgItemInt(hWnd, IDC_RHS, &success, true); if(!success){ MessageBox(hWnd, TEXT("the second expression is not an integer。"), TEXT("Error"), MB_OK); break; } int result = 0; switch(op){ case ADD: result = lhs + rhs; break; case SUB: result = lhs - rhs; break; case MULT: result = lhs * rhs; break; case REM: if(rhs == 0){ SetDlgItemText(hWnd, IDC_RESULT, TEXT("Underfined")); }else { result = lhs % rhs; } } SetDlgItemInt(hWnd, IDC_RESULT, result, true); break; }

如图:
wm_button

生成工程

小结

  1. 面向对象的角度
    windows平台的窗口虽然已经有了面向对象的思想,而且把窗口中的空间也看作是特殊的窗口,从上面的程序也可以看出,在访问子控件的内容时(GetDlgItemInt(hWnd, IDC_LHS, &success, true);),并不像java swing那样的纯面向对象(JTextField tf;int n = Integer.parseInt(tf.getText());)。从这个角度看,windows的窗口并不是面向对象,而且不像传统的对象(含有传统的数值成员变量)和swing中的对象(像对象一样访问其内容tf.getText())
  2. 编程最基本的问题之数据访问
    最开始在接受了把窗口看做对象的思想时(特别是MFC之socket编程总结:面向对象文章中,窗口对象中添加了,socket对象),就把窗口中的控件看做对象,在访问时总是面向对象的思路(swing的思想),上面也可以看出来,实际上窗口并没有显示的子控件对象,所以这种思路也不行。在GUI环境下,访问数据不再只有对象、变量的形式,还有有API决定方式,如上面的使用GetDlgItemInt函数和窗口句柄
  3. 上面两个角度总结一下
    拿访问编辑框的内容为例
  1. 通过子窗口句柄,Int GetWindowText(HWND hWnd,LPTSTR lpString,Int nMaxCount),需要在创建子控件的时候保存窗口句柄
  2. 通过资源ID,此时还需要父窗口句柄。UINT GetDlgItemInt(int nID, BOOL* lpTrans = NULL, BOOL bSigned = TRUE)
  3. 1、2的结合,即创建控件时不保存句柄,而是通过资源ID来获取子控件窗口句柄,HWND GetDlgItem(HWNDhDlg, intnIDDlgItem),网上例子:Win32 Examples: Net Price Calculation。
  4. MFC中的窗口,只有顶层的窗口可以添加传统的数值型的成员变量,其子控件的获取也可以通过1、2、3方法得到,当然也可以通过DDX机制实现,而DDX又分为DDX_Control、DDX_Text,DDX_Text还是没有纯OO的思想,而DDX_Control体现了纯OO对象。
  5. 多窗口应用程序中顶层窗口可以有数值型的成员变量,而且可以通过对象访问。
  6. 所以往往是OP的接口+OO的思想,如GetWindowText,OP的接口,而HWND hWnd貌似OO单也不算是对象(对象的索引),再如 extern DECLSPEC int SDLCALL SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect, const double angle, const SDL_Point *center, const SDL_RendererFlip flip); 是否可以把SDL_RenderCopyEx作为SDL_Renderer(如果把SDL_Renderer这个结构体封装成类)的方法。另一方面可以把SDL_RenderCopyEx看做SDL(虚拟)这个类的方法,这样的话SDL_RenderCopyEx这个功能的划分到底是划分给SDL呢,还是SDL_Renderer呢??