源自网络收集,仅供参考
实验三收集到两份完整报告,这是其一,另一份见本专栏下一篇文章。
实验题目
《面向对象程序设计》 实验三
实验题目:子窗口与控件的基本用法、资源的使用
整体目的:理解、窗口之间的消息传送、调用栈;掌握光标、图标、菜单的制作和使用方式;掌握菜单的响应方式、快捷菜单的载入及使用方式;理解GetWindowLong/SetWindowLong, GetClassLong/SetClassLong函数的用法。
实验内容过程:
改进ChildWin示例程序,在子窗口内显示出窗口特定信息(窗口ID号);尝试在每个子窗口中绘制特定颜色的矩形
-
- 在子窗口的窗口过程函数的刷新处理消息中增添处理代码;
- 用GetWindowLong函数取出子窗口ID;
- 根据子窗口ID设定子窗口内需要显示的信息(使用wsprintf函数组织待显示的字符串)
- 尝试在子窗口中绘制特定颜色的矩形(使用CreateSolidBrush、Rectangle函数)
- 跟踪消息传递过程
- 在Childwin的主窗口过程函数的WM_CREATE、WM_PAINT、WM_COMMAND、WM_LBUTTONDOWN处设置断点
- 在子窗口的WM_CREATE、WM_PAINT、WM_CHILDWIN、WM_LBUTTONDOWN处设置断点
- 运行程序,查看各断点的响应过程,以此理解消息传递的次序
- 设计、实现一个软键盘
用子窗口实现一个软键盘(在窗口的客户区用子窗口绘制一个仿真的键盘),鼠标点击每个子窗口,可输入不同的字符。将输入的字符显示到窗口中。
- 在自己的工作目录中建立新工程用于控件测试〔可以将Easywin工程的easywin.c拷贝到新工程的目录中,修改文件名为ctltest.cpp(后缀名改为.cpp),编译、链接并使程序正常工作(包括修正编译错误)〕。
- * 用Button完成4*所要求的软键盘实现。比较与原有实现的不同之处。
- 创建各种类型的控件子窗口,包括static、edit、listbox、combobox、button、scrollbar等;在主窗口的窗口过程函数中增加相应的消息处理实现主窗口与子窗口的通信(可尝试设置控件的标题/内容,获取控件的标题/内容以及在控件有点击等操作时在主窗口给出提示)。
- 同步骤5,新建用于资源测试的工程。
- 增加新的资源:光标、图标,并正确显示
- 用资源编辑器编辑一个光标(彩色),注意删除资源中不需要的image类型,否则显示光标可能不正确。
- 为光标设定热点(hot spot)
- 用资源编辑器编辑一个图标
- 修改注册窗口类的代码,使程序能正常使用自定义的光标和图标
- 用DrawIcon函数,在WM_PAINT消息中增加处理,在窗口客户区中显示自定义的光标及图标。
- 创建一个另外光标供后续实验步骤使用
- 增加菜单
- 菜单中建立一个菜单项命令以修改窗口使用的光标,可命名为“ChangeCursor”,对应的ID假设为ID_CHANGECURSOR
- 修改注册窗口类的代码,使程序运行时能正确载入菜单
- 换一种方式,通过修改创建窗口(CreateWindow)的代码,使菜单能正确载入
- 增加菜单消息响应代码
- 增加WM_COMMAND的消息处理
- 参照第五章菜单示例代码中的处理方式,响应菜单命令
- 对ID_CHANGECURSOR命令的响应为:改变窗口使用的光标,可以使用SetClassLong (hwnd, GCL_HCURSOR,
(LONG)LoadCursor((HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
MAKEINTRESOURCE(IDC_CURSOR2) ) );
- 处理鼠标右键,增加快捷菜单处理
- 右键发出的菜单命令同样是通过WM_COMMAND消息响应的,增加快捷菜单之后,程序应该能通过主菜单或快捷菜单两种方式发出同样的命令
- 将本次实验做好的工程的编译、链接增加到程序构建使用的批处理文件中,用批处理文件一次性自动构建实验一、二、三的所有工程。
- 本次实验的实验报告上交时间为10月22日 21:30之前。
注意:
- 5* 选做。
- 做好各次实验的备份,每次实验课时携带所有先前实验的实验成果(电子版)备查。
- 实验报告文档格式、文件名应符合要求。
实验报告1(另一份报告见本专栏下一篇文章)
-
实验要求
理解、窗口之间的消息传送、调用栈;掌握光标、图标、菜单的制作和使用方式;掌握菜单的响应方式、快捷菜单的载入及使用方式;理解GetWindowLong/SetWindowLong, GetClassLong/SetClassLong函数的用法。
2,实验过程及结果
2.1创建工程
2.2程序流程和数据模型分析
- 改进ChildWin示例程序,在子窗口内显示出窗口特定信息(窗口ID号);尝试在每个子窗口中绘制特定颜色的矩形
- 在子窗口的窗口过程函数的刷新处理消息中增添处理代码;
- 用GetWindowLong函数取出子窗口ID;
- 根据子窗口ID设定子窗口内需要显示的信息(使用wsprintf函数组织待显示的字符串)
- 尝试在子窗口中绘制特定颜色的矩形(使用CreateSolidBrush、Rectangle函数)
2.跟踪消息传递过程
在Childwin的主窗口过程函数的WM_CREATE、WM_PAINT、WM_COMMAND、
-
- WM_LBUTTONDOWN处设置断点
- 在子窗口的WM_CREATE、WM_PAINT、WM_CHILDWIN、WM_LBUTTONDOWN处设置断点
- 运行程序,查看各断点的响应过程,以此理解消息传递的次序
3.设计、实现一个软键盘
用子窗口实现一个软键盘(在窗口的客户区用子窗口绘制一个仿真的键盘),鼠标点击每个子窗口,可输入不同的字符。将输入的字符显示到窗口中。
4.在自己的工作目录中建立新工程用于控件测试〔可以将Easywin工程的easywin.c拷贝到新工程的目录中,修改文件名为ctltest.cpp(后缀名改为.cpp),编译、链接并使程序正常工作(包括修正编译错误)〕
- * 用Button完成4*所要求的软键盘实现。比较与原有实现的不同之处。
- 创建各种类型的控件子窗口,包括static、edit、listbox、combobox、button、scrollbar等;在主窗口的窗口过程函数中增加相应的消息处理实现主窗口与子窗口的通信(可尝试设置控件的标题/内容,获取控件的标题/内容以及在控件有点击等操作时在主窗口给出提示)。
- 同步骤4,新建用于资源测试的工程。
- 增加新的资源:光标、图标,并正确显示
- 用资源编辑器编辑一个光标(彩色),注意删除资源中不需要的image类型,否则显示光标可能不正确。
- 为光标设定热点(hot spot)
- 用资源编辑器编辑一个图标
- 修改注册窗口类的代码,使程序能正常使用自定义的光标和图标
- 用DrawIcon函数,在WM_PAINT消息中增加处理,在窗口客户区中显示自定义的光标及图标。
- 创建一个另外光标供后续实验步骤使用
9. 增加菜单
- 增加菜单
- 菜单中建立一个菜单项命令以修改窗口使用的光标,可命名为“ChangeCursor”,对应的ID假设为ID_CHANGECURSOR
- 修改注册窗口类的代码,使程序运行时能正确载入菜单
- 换一种方式,通过修改创建窗口(CreateWindow)的代码,使菜单能正确载入
- 增加菜单消息响应代码
- 增加WM_COMMAND的消息处理
- 参照第五章菜单示例代码中的处理方式,响应菜单命令
- 对ID_CHANGECURSOR命令的响应为:改变窗口使用的光标,可以使用SetClassLong (hwnd, GCL_HCURSOR,
(LONG)LoadCursor((HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
MAKEINTRESOURCE(IDC_CURSOR2) ) );
- 处理鼠标右键,增加快捷菜单处理
右键发出的菜单命令同样是通过WM_COMMAND消息响应的,增加快捷菜单之后,程序应该能通过主菜单或快捷菜单两种方式发出同样的命令
- 将本次实验做好的工程的编译、链接增加到程序构建使用的批处理文件中,用批处理文件一次性自动构建实验一、二、三的所有工程。
2.3问题及解决方案
- 在主窗口设置的光标无法在子窗口显示,为了在子窗口设置自己的光标,我使用了全局变量进行编写子窗口的光标程序;
- 由于paint中我使用了if条件语句,导致本软键盘第一个按键无法作用,按下后无法刷新,所以将所有字母向后移动一位(也可以不后移,设置全局变量代替if语句进行绘制判断即可);
- 快捷方式写好后无法运行,经检查为 g_hSubMenu = GetSubMenu(g_hMenu, 0);语句写在return语句后面,导致无法正常运行,但系统又无法报错。
3.实验总结
在本次试验中,我不仅将老师上课所讲的窗口知识和菜单知识进行实践的运用,掌握了绘制光标,绘制图标的能力,掌握了菜单的制作和使用、响应方式,快捷菜单的载入及使用方式,还通过上网搜索等方法了解了许多课外函数,如:GetCursorPos(),TrackPopupMenu()等。不仅锻炼了自己的独立思考能力还拓宽了眼界。
附录 关键代码
软键盘绘制代码:
case WM_PAINT:
GetClientRect(hWnd, &rect);
hdc = BeginPaint(hWnd, &ps);
if (!(LOWORD(wParam) == nChildWin_ID))
{
string[n] = number + 65;
n++;
DrawText(hdc, string, n, &rect, DT_SINGLELINE);
}
DrawIcon(hdc,1,1, LoadIcon(hin, MAKEINTRESOURCE(IDI_ICON1)));
EndPaint(hWnd, &ps);
return 0;
子窗口命中写入代码:
case WM_COMMAND:
if (!(LOWORD(wParam) == nChildWin_ID))
{
SendMessage((HWND)hChildWnd[nCol][nRow], WM_CHILDWIN, 0, 0L);
nChildWin_ID = LOWORD(wParam);
nCol = nChildWin_ID >> 4;
nRow = (nChildWin_ID > 15) ? (nChildWin_ID - 4) : nChildWin_ID;
}
else
{
switch (wParam)
{
case ID_CHANGECURSOR:
SetClassLong(hWnd, GCL_HCURSOR,
(LONG)LoadCursor((HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
MAKEINTRESOURCE(IDC_CURSOR1)));
break;
}
}
InvalidateRect(hWnd, NULL, TRUE);
return 0;
主窗口绘制菜单,光标,图形代码:
wcMain.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));
wcMain.hCursor = LoadCursor(hInstance, MAKEINTRESOURCE (IDC_CURSOR2));
wcMain.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wcMain.lpszMenuName = MAKEINTRESOURCE(IDR_MENU3);
改变光标菜单代码:
case WM_COMMAND:
if (!(LOWORD(wParam) == nChildWin_ID))
{
SendMessage((HWND)hChildWnd[nCol][nRow], WM_CHILDWIN, 0, 0L);
nChildWin_ID = LOWORD(wParam);
nCol = nChildWin_ID >> 4;
nRow = (nChildWin_ID > 15) ? (nChildWin_ID - 4) : nChildWin_ID;
}
else
{
switch (wParam)
{
case ID_CHANGECURSOR:
SetClassLong(hWnd, GCL_HCURSOR,
(LONG)LoadCursor((HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
MAKEINTRESOURCE(IDC_CURSOR1)));
break;
}
}
InvalidateRect(hWnd, NULL, TRUE);
return 0;
右键快捷菜单代码:
case WM_RBUTTONDOWN:
GetCursorPos(&stPos);
TrackPopupMenu(g_hSubMenu,TPM_LEFTALIGN,stPos.x,stPos.y,NULL,hWnd,NULL);
break;