实验一:一元二次方程的求解
- 新建Win32应用程序(非Win32控制台程序)
- 新建xxx.cpp文件用来放置代码,具体代码如下:
#include <windows.h>
#include <stdio.h>
#include <Math.h>
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lparam); //窗口过程函数声明
GetRoot(float a, float b, float c, double *root);
char str[80]; // 全局变量
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) //主函数
{
//窗口创建五步曲
//1.设计一个完整的窗口类
static TCHAR szAppName[] = TEXT ("HelloWinAPI");
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;// 窗口类名
//2.注册窗口类
if (!RegisterClass(&wndclass)) //设计完窗口后,需要对窗口类进行注册,这样才能创建该类型的窗口
return - 1;
//3.正式创建窗口
hwnd = CreateWindow(szAppName, szAppName, WS_OVERLAPPEDWINDOW, 10, 10, 600, 400, NULL, NULL, hInstance, NULL);
//4.窗口的显示与更新
ShowWindow(hwnd, nShowCmd); //调用ShowWindow函数来显示窗口
UpdateWindow(hwnd); //对窗口进行更新
//5.消息循环过程
while (msg.message != WM_QUIT) //使用while循环,如果消息不是WM_QUIT消息,就继续循环
{
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) //查看应用程序消息队列,有消息时将队列中的消息派发出去。
{
TranslateMessage(&msg); //将虚拟键消息转换为字符消息
DispatchMessage(&msg); //分发一个消息给窗口程序。
}
}
//窗口类的注销
UnregisterClass(szAppName, wndclass.hInstance); //程序准备结束,注销窗口类
return 0;
}
// 窗口过程函数WndProc,对窗口消息进行处理
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
HDC hdc;
PAINTSTRUCT ps;
static HWND hwndButton, hwndEdit;
char strEdit[80], strA[3][80], strHint[80];
float a[3];
double root[2];
int i, j, k, m;
switch (message)
{
case WM_CREATE: // 窗口创建产生的消息
hwndEdit=CreateWindow("edit",NULL,
WS_CHILD|WS_VISIBLE|WS_BORDER,
10, 60, 200, 25, hwnd, NULL, NULL, NULL );
hwndButton = CreateWindow("button", "计 算",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
240, 60, 80, 25, hwnd, NULL, NULL, NULL );
return 0 ;
case WM_COMMAND:// 命令消息,控件产生的通知代码在 wParam 的高字中
if (((HWND)lParam==hwndButton)&&(HIWORD(wParam) == BN_CLICKED ))
// 单击按钮
{
// 获取编辑框控件的内容,并将其转换成 float 数值
GetWindowText( hwndEdit, strEdit, 80); // 获取编辑框内容
k = 0; m = 0;
for (j=0; j<80; j++)
{
if (strEdit[j] == ','){
k++; m = 0;
}
else {
strA[k][m] = strEdit[j];
m++;
}
}
for (i=0; i<3; i++)
a[i] = (float)atof(strA[i]); // 将字符串转换成 float 数值
int n = GetRoot(a[0], a[1], a[2], root);
if (n < 1) strcpy(str, "方程无根!") ;
else sprintf(str, "方程的解为:%f, %f", root[0], root[1]);
InvalidateRect(hwnd, NULL, TRUE);
}
case WM_PAINT: //绘制窗口
hdc = BeginPaint(hwnd, &ps);
strcpy(strHint, "请输入一元二次方程的 3 个系数,中间用逗号分隔");
TextOut(hdc, 10, 40, strHint, strlen(strHint));
TextOut(hdc, 10, 90, str, strlen(str));
EndPaint(hwnd, &ps);
//和 BeginPaint()函数配对使用,以便使用完系统资源 hdc 后,立刻释放资源
return 0 ;
case WM_DESTROY:// 当窗口关闭时产生的消息
PostQuitMessage(0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;// 执行默认的消息处理
}
int GetRoot(float a, float b, float c, double *root) {
double delta, deltasqrt;
delta = b*b - 4.0 * a * c;
if (delta<0.0) return 0; // 无根
deltasqrt = sqrt(delta);
if (a!=0.0) {
root[0] = (-b + deltasqrt) / (2.0 * a);
root[1] = (-b - deltasqrt) / (2.0 * a);
}
else
if (b != 0.0)
root[0] = root[1] = -c / b;
else return 0;
if (root[0] == root[1]) return 1;
else return 2;
}
实验二:鼠标与键盘事件
- 鼠标左右键自增与自减事件
1.在View视图类新建公共变量:int M_Right; int M_Left;
2.在View视图类构造器中完成变量初始化:M_Left = 0; M_Right = 0;
3.在建立类向导中选择View试图类,生成如下两个Messages:VM_OnLButtonDown()、VM_OnRButtonDown()
4.添加OnLButtonDown()与OnRButtonDown()处理函数:
OnLButtonDown():
M_Left++;
CString strOutput;
strOutput.Format("鼠标左键的点击次数为:%d", M_Left);
MessageBox(strOutput);
CView::OnLButtonDown(nFlags, point);
OnRButtonDown():
M_Right++;
CString strOutput;
strOutput.Format("鼠标右键的点击次数为:%d", M_Right);
MessageBox(strOutput);
CView::OnRButtonDown(nFlags, point);
- 键盘弹出事件
1.在建立类向导中选择View试图类,生成一个Messages:VM_CHAR()
2.添加VM_CHAR()处理函数:
if (nChar == 'X') {
MessageBox("您的学号为:hehe");
}
CView::OnChar(nChar, nRepCnt, nFlags);
实验三:图形与文本
1.使用不同的画笔绘制自己的姓名
- 在View视图通过补充OnDraw()函数完成名字的绘制:
CDrawNameDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CPen pen0(PS_DASH, 1, RGB(0, 0, 0));
pDC->SelectObject(&pen0);
pDC->MoveTo(150, 150);
pDC->LineTo(250, 150);
CPen pen1(PS_DOT, 1, RGB(0, 0, 0));
pDC->SelectObject(&pen1);
pDC->MoveTo(250, 150);
pDC->LineTo(250, 250);
CPen pen2(PS_SOLID, 1, RGB(0, 0, 0));
pDC->SelectObject(&pen2);
pDC->MoveTo(180, 150);
pDC->LineTo(180, 250);
CPen pen3(PS_DASHDOT, 1, RGB(0, 0, 0));
pDC->SelectObject(&pen3);
pDC->MoveTo(180, 250);
pDC->LineTo(300, 250);
CPen pen4(PS_INSIDEFRAME, 1, RGB(0, 0, 0));
pDC->SelectObject(&pen4);
pDC->MoveTo(300, 250);
pDC->LineTo(300, 350);
CPen pen5(PS_INSIDEFRAME, 1, RGB(0, 0, 0));
pDC->SelectObject(&pen5);
pDC->MoveTo(300, 350);
pDC->LineTo(280, 330);
CPen pen6(PS_DASHDOTDOT, 1, RGB(0, 0, 0));
pDC->SelectObject(&pen6);
pDC->MoveTo(160, 300);
pDC->LineTo(300, 300);
2.使用不同的画刷模拟交通信号灯
CPen pen(NULL, 1, RGB(0, 0, 0));
pDC->SelectObject(&pen);
// 画圆1
pDC->Ellipse(20, 20, 120, 120); // 参数为:左上角:(x, y)、右上角:(x, y)
// 画刷:上色
CBrush brush(RGB(255, 0, 0));
pDC->SelectObject(&brush);
pDC->Ellipse(20, 20, 120, 120);
pDC->SelectObject(&pen);
pDC->Ellipse(20, 150, 120, 250);
CBrush brush1(RGB(255, 255, 0));
pDC->SelectObject(&brush1);
pDC->Ellipse(20, 150, 120, 250);
pDC->SelectObject(&pen);
pDC->Ellipse(20, 280, 120, 380);
CBrush brush2(RGB(0, 255, 0));
pDC->SelectObject(&brush2);
pDC->Ellipse(20, 280, 120, 380);
3.补充字体的使用:
CFont *OldFont, NewFont1;
NewFont1.CreatePointFont(200, "宋体", NULL);
OldFont = pDC->SelectObject(&NewFont1);
pDC->TextOut(0,60, "导入背景图片");
pDC->SelectObject (OldFont);
NewFont1.DeleteObject();
实验四:菜单栏与工具栏
1.菜单栏:添加主菜单“显示”,“显示”菜单中包含“文本”和“图形”两个子菜单。点击“文本”,显示“菜单设计程序”;点击“图形”,显示一个红色的实心矩形
- 在ResourceView中的Menu资源完成新的菜单项的定义与属性ID的定义(ID_TEXT与ID_PICTURE)
- 在View中Doc类中新建全局变量int picture;,添加在Doc类的构造函数最前面
- 在类向导中选择Doc类,分别对刚才定义的ID添加COMMAND处理函数:OnText()与OnPicture()
OnText():
picture = 0;
UpdateAllViews(NULL);
picture = 2;
UpdateAllViews(NULL);
OnPicture():
picture = 0;
UpdateAllViews(NULL);
picture = 1;
UpdateAllViews(NULL);
- 并在视图类补充完成OnDraw()函数:对应OnDraw()文件前使用extern int picture;
CDraw1Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
if (picture == 1) {
CPen pen(NULL, 1, RGB(0, 0, 0));
pDC->SelectObject(&pen);
// 画矩形
pDC->Rectangle(20, 20, 120, 120);
// 画刷
CBrush brush(RGB(255, 0, 0));
pDC->SelectObject(&brush);
pDC->Rectangle(20, 20, 120, 120);
}
if (picture == 2) {
CFont *OldFont, NewFont1;
NewFont1.CreatePointFont(200, "宋体", NULL);
OldFont = pDC->SelectObject(&NewFont1);
pDC->TextOut(0,60, "菜单设计程序");
pDC->SelectObject (OldFont);
NewFont1.DeleteObject();
}
2.工具栏:为应用程序添加两个工具栏按钮,单击第一个按钮,在视图中弹出“打开”对话框;单击第二个按钮,在消息框中显示“工具栏设计程序”
- 在ResourceView中的ToorBar资源完成新的工具栏的定义与属性ID的定义(ID_OPEN与ID_SHOW)
- 在建立类向导中的Doc类中选择对应ID,并添加ONCOMMAND函数:OnOpen()与OnShow()函数
OnOpen():
AfxMessageBox("打开");
UpdateAllViews(NULL);
OnShow():
AfxMessageBox("工具栏设计程序");
UpdateAllViews(NULL);
实验五:模态对话框与非模态对话框
1.模态对话框:编写一个 SDI 应用程序,执行某一菜单命令时打开一个模态对话框,在对话框中输入一对坐标值,单击 OK 按钮后在视图中该坐标位置显示自己的姓名。
- 新建一个Dialog资源,向其添加文本和编辑框控件并修改ID(IDC_EDIT1)
- 添加与控件关联的成员变量。启动类向导,单击Member Variables标签。在Class name下拉框选择新建的Dialog资源类,在Control IDs栏选择自己设定好的编辑框资源ID,单击Add Variable按钮。通过 Add Member Variable对话框添加成员变量m_Coor,类型为CString
- 为了在视图对象中接收并存储编辑控件的值,在C****View中手 工定义一个CString类型的成员变量str,并新建int x与int y进行坐标的获取
- 利用菜单编辑器在“编辑”菜单增加一个菜单项“输入坐标”,其ID标识 为ID_INPUTCOOR。启动ClassWzard类向导,在视图类中为菜单项添加消息COMMAND的处理函数(注意这里对CString类型转换处理int)
COMMAND()函数:
CCoorDialog dlg; // 定义一个对话框对象
dlg.m_Coor = "50,50"; // 设置编辑框显示的初始值
if (dlg.DoModal()==IDOK) // 显示对话框
{
str = dlg.m_Coor; // 接收并存储编辑框数据
Invalidate(); // 刷新视图
}
int n = str.ReverseFind('.');
CString x_str = str.Left(str.GetLength() - n - 1);
CString y_str = str.Right(str.GetLength() - n - 1);
sscanf(x_str,"%d",&x); // 将字符串转为已定义的int x坐标
sscanf(y_str,"%d",&y);
- 在View类的OnDraw()函数中完成名字绘制
OnDraw()函数:
CString name = "MT";
CFont *OldFont, NewFont;
LOGFONT MyFont = {30, 10, 0, 0, 0, 1, 1, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "黑体" };
NewFont.CreateFont (30, 10, 0, 0, FW_HEAVY, false, false, false, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE, "大号字");
OldFont = pDC->SelectObject(&NewFont); // 这里使用从窗口获得的x与y
pDC->TextOut(x, y, name);
pDC->SelectObject(OldFont);
NewFont.DeleteObject();
- 在****View.cpp中添加#include “自定义类.h”
2.非模态对话框:编写一个 SDI 应用程序,执行某一菜单命令时打开一个非模态对话框,在对话框中输入一对坐标值,单击 OK 按钮后在视图中该坐标位置显示自己的学号
- 新建一个Dialog资源,向其添加文本和编辑框控件并修改ID
- 添加与控件关联的成员变量。定义为m_Coor,CString类型
- 在视图类添加一个与成员变量完全相同的变量CString m_Coor,否则无法完成绑定
- 在 C***View视图类中增加新建类指针类型的公有成员变量 m_pDlg。在***View.h文件的头部预编译命令之前增加类的前向声明语如下: class C新建类; class C***Doc;
- 在自定义类中增加C***View指针类型的公有成员变量m_pParent,再在当前文件中添加class C***View 并在自定义类类的构造函数中添加该变量初始化语句m_pParent=(C**View)pParent; 在自定义类.h文件的头部预编译命令之前增加类的前向声明语句:class C***View;
- 在***View.cpp文件的头部所有的include语句之后添加对话框类的头文件。#include “自定义类.h”
- 增加菜单项使用菜单编辑器在主菜单中增加一个【对话框】菜单项,并在其中添加【非模态对话框】菜单项,其ID为ID_NOMODEDLG,用ClassWizard在视图类中为ID_NOMODEDLG菜单项添加COMMAND消息的处理函数,在OnNomodedlg()函数中添加如下代码
if(!m_pDlg)
m_pDlg->SetActiveWindow();//激活非模态对话框
else
{
//创建非模态对话框
m_pDlg = new CCoorDialog(this); //创建对话框对象
m_pDlg->m_pParent = this;//获取主窗口视图指针
m_pDlg->Create(IDD_DIALOG1, this); //创建对话框
m_pDlg->ShowWindow(SW_SHOW); //显示对话框
}
Invalidate();
- 在自定义类.cpp文件的头部所有的include语句之后添加视图类的头文件。#include “***View.h”
- 利用ClassWizard为对话框中的确定和取消按钮添加处理函数
OnOk():
CDialog::OnOK();
CClientDC dc(m_pParent);
UpdateData(true); //获取用户数据
// 更新用户数据
int n = m_Coor.ReverseFind('.');
CString x_str = m_Coor.Left(m_Coor.GetLength() - n - 1);
CString y_str = m_Coor.Right(m_Coor.GetLength() - n - 1);
int x, y;
sscanf(x_str,"%d",&x); // 将字符串转为已定义的int x坐标
sscanf(y_str,"%d",&y);
CString name = "123456789";
dc.TextOut(x, y, name, name.GetLength());
OnCancel():
CDialog::OnCancel();
if(m_pParent!=NULL) {
m_pParent->m_pDlg = NULL;//表明对话框对象已不存在了
DestroyWindow(); //删除对话框窗口
}
- 利用ClassWizard在对话框类”C自定义类”中添加PostNcDestroy消息,并添加如下代码:
CDialog::PostNcDestroy();
delete this;//删除对话框对象
实验六:编写一个单文档应用程序,用菜单栏打开一个对话框,通过该对话框中的红色、绿色和蓝色复选按钮选择颜色,在视图中绘制不同颜色矩形
- 新建一个Dialog资源,向其添加复选框并修改ID
- 添加与控件关联的成员变量。启动类向导,单击Member Variables标签。在Class name下拉框选择新建一个Dialog资源类,在Control IDs栏选择自己设定好的编辑框资源ID,单击Add Variable按钮。通过 Add Member Variable添加成员变量m_Red, m_Green,m_Blue均为BOOL
- 为了在视图对象中接收并存储编辑控件的值,在C****View中手 工定义三个BOOL类型的m_Red, m_Green,m_Blue
- 利用菜单编辑器在“编辑”菜单增加一个菜单项“矩形”,其ID标识为 ID_INPUTT。启动ClassWzard类向导,在视图类中为菜单项添加消息COMMAND的处理函数
CTColorDialog dlg; // 定义一个对话框对象,重定义需要修改
dlg.m_Red = true; // 设置编辑框显示的初始值
if (dlg.DoModal() == IDOK) // 显示对话框
{
m_Red = dlg.m_Red; // 接收并存储编辑框数据
m_Green = dlg.m_Green;
m_Blue = dlg.m_Blue;
flag = 3; // 更新视图,避免非法显示,如果使用flag = 1 改变int flag;会产生奇怪的错误
Invalidate(); // 刷新视图
}
- 在View类的OnDraw()函数中完成图形绘制
if(flag == 3) {
CPen pen(NULL, 1, RGB(0, 0, 0));
pDC->SelectObject(&pen);
if (m_Red) {
// 画矩形1
pDC->Rectangle(20, 20, 120, 120); // 四个参数分别为对应的两组坐标,左上和右下
// 画刷
CBrush brush(RGB(255, 0, 0));
pDC->SelectObject(&brush);
pDC->Rectangle(20, 20, 120, 120);
pDC->SelectObject(&pen);
}
if (m_Blue) {
pDC->Rectangle(280, 20, 380, 120);
// 画刷
CBrush brush(RGB(0, 0, 255));
pDC->SelectObject(&brush);
pDC->Rectangle(280, 20, 380, 120);
pDC->SelectObject(&pen);
}
if (m_Green) {
pDC->Rectangle(150, 20, 250, 120);
// 画刷
CBrush brush(RGB(0, 255, 0));
pDC->SelectObject(&brush);
pDC->Rectangle(150, 20, 250, 120);
pDC->SelectObject(&pen);
}
}
- 在****View.cpp中添加#include “自定义类.h”