界面展示
我们利用前面所学的知识做一个图形界面的通信录,如下所示
利用listview做通信录信息的显示
然后添加4个按钮,添加,删除,修改和查询
点击添加和修改按钮会弹出 dialog窗口,进行编辑
输入信息后,
点击确定,则完成操作
代码实例
主要界面代码实例
//主窗口回调函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
/*回调函数
参数:
hwnd : 窗口句柄
message : 消息ID
wParam和lParam:消息参数*/
HDC hdc;
static TCHAR szBuffer[128];
static HWND childHwnd; //子窗口句柄
static HWND hBtn, hBtn2, hBtn3, hBtn4;
static int i,szlist;
PAINTSTRUCT ps;
static HWND hListview;
static LV_COLUMN lvc;//LVCOLUMN结构体,定义listview的列属性
static LVITEM vitem;//LVITEM结构体,定义listview的项的数据属性
static int idComboBox;
int n,wmId, wmEvent;
//static int nSelectItem;
int nSelectIndex;
init(&contactlist);//初始化通信录
switch (message)
{
case WM_SIZE:
{
hdc = GetDC(hWnd);
cxClient = LOWORD(lParam);//当前x像素
cyClient = HIWORD(lParam);//当前y像素
//wsprintf(szBuffer, TEXT("%d,%d"), cxClient, cyClient);
ReleaseDC(hWnd, hdc);
return 0;
}
//定义父窗口回调函数 WndProc, 在处理 WM_CREATE 消息时创建子窗口:
case WM_CREATE: //在接收到 WM_CREATE 消息时创建一个子窗口
{
//创建逻辑字体
hFont = CreateFont(
-18/*高度*/, -9/*宽度*/, 0, 0, 400 /*一般这个值设为400*/,
FALSE/*不带斜体*/, FALSE/*不带下划线*/, FALSE/*不带删除线*/,
DEFAULT_CHARSET, //使用默认字符集
OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, //这行参数不用管
DEFAULT_QUALITY, //默认输出质量
FF_DONTCARE, //不指定字体族*/
TEXT("微软雅黑")); //字体名
//创建listview子窗口
hListview = CreateWindow(TEXT("SysListView32"), TEXT("LISTVIEW"),
WS_VISIBLE | WS_CHILD | WS_BORDER | LVS_REPORT | LVS_SHOWSELALWAYS,
/*WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN
| LVS_REPORT | LVS_AUTOARRANGE | LVS_SHOWSELALWAYS
| LVS_SHAREIMAGELISTS | LVS_SINGLESEL,*/
10, 10, 550, 490,
hWnd, NULL, hInst, NULL);
ListView_SetExtendedListViewStyle(hListview, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES | LVS_EX_GRIDLINES);
/*
LVS_EX_FULLROWSELECT 选中高亮,可以进行整行选中
LVS_EX_CHECKBOXES 勾选框
LVS_EX_GRIDLINES 网格线
*/
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;//指定哪些成员包含有效信息的变量。该成员可以是零
lvc.fmt = LVCFMT_CENTER; //列标题与列中子项文本的对齐方式。最左边一列的对齐方式始终是 LVCFMT_LEFT;
lvc.pszText = TEXT("ID");//列的名称,如果正在设置列信息,则此成员是包含列标题文本的以空字符结尾的字符串的地址
lvc.cx = 0;//设置列的宽度 ,这样就不会显示第一列
SendMessage(hListview, LVM_INSERTCOLUMN, 0, (LPARAM)&lvc); //LVM_INSERTCOLUMN表示添加列表示添加列,给第1列添加标体
lvc.pszText = TEXT("姓名");//列的名称,如果正在设置列信息,则此成员是包含列标题文本的以空字符结尾的字符串的地址
lvc.cx = 100;//设置列的宽度
SendMessage(hListview, LVM_INSERTCOLUMN, 1, (LPARAM)&lvc); //LVM_INSERTCOLUMN表示添加列表示添加列,给第1列添加标体
lvc.pszText = TEXT("年龄");
lvc.cx = 100;
SendMessage(hListview, LVM_INSERTCOLUMN, 2, (LPARAM)&lvc);
lvc.pszText = TEXT("电话");
lvc.cx = 100;
SendMessage(hListview, LVM_INSERTCOLUMN, 3, (LPARAM)&lvc);
lvc.pszText = TEXT("地址");
//lvc.cx = cxClient - 400;
SendMessage(hListview, LVM_INSERTCOLUMN, 4, (LPARAM)&lvc);
ListView_SetColumnWidth(hListview,4, LVSCW_AUTOSIZE_USEHEADER);
//SendMessage(hListview, LVM_SETTEXTCOLOR, 0, RGB(255, 255, 255));//设置文字颜色
//SendMessage(hListview, LVM_SETTEXTBKCOLOR, 0, RGB(100, 0, 200));//设置文字背景颜色
//SendMessage(hListview, LVM_SETBKCOLOR, 0, RGB(150, 255, 50));//设置控件背景颜色
vitem.mask = LVIF_TEXT;
szlist = contactlist.size;//获得通信录大小
for (i = 0; i < szlist; i++)
{
//先添加项再设置子项内容
//插入第一行数据,这一段代码是不可以少的。
vitem.iItem = i;//第几行的数据
vitem.iSubItem = 0;//第1列
SendMessage(hListview, LVM_INSERTITEM, 0, (LPARAM)&vitem);//第一列为空数据,不添加数据。
vitem.iSubItem = 1;//第2列
vitem.cchTextMax = 20;
vitem.pszText = contactlist.data[i].name;
ListView_SetItem(hListview, &vitem);
// 设置子项
vitem.iSubItem = 2;//第3列
vitem.pszText = contactlist.data[i].age;
ListView_SetItem(hListview, &vitem);
vitem.iSubItem = 3;//第4列
vitem.pszText = contactlist.data[i].tel;
ListView_SetItem(hListview, &vitem);
vitem.iSubItem = 4;//第5列
vitem.pszText = contactlist.data[i].address;
ListView_SetItem(hListview, &vitem);
}
//添加按钮控件
hBtn = CreateWindow(TEXT("button"), TEXT("添加"),
WS_CHILD | WS_VISIBLE | WS_BORDER | BS_DEFPUSHBUTTON, //*默认按钮样式*/,
570 /*X坐标*/, 20 /*Y坐标*/, 80 /*宽度*/, 30/*高度*/,
hWnd, (HMENU)1 /*控件唯一标识符*/, hInst, NULL);
SendMessage(hBtn, WM_SETFONT, (WPARAM)hFont, 0);//设置按钮字体
//删除按钮控件
hBtn2 = CreateWindow(
TEXT("button"), //按钮控件的类名
TEXT("删除"),
WS_CHILD | WS_VISIBLE | WS_BORDER | BS_DEFPUSHBUTTON, //*默认按钮样式*/,
570 /*X坐标*/, 60 /*Y坐标*/, 80 /*宽度*/, 30/*高度*/,
hWnd, (HMENU)2 /*控件唯一标识符*/, hInst, NULL);
SendMessage(hBtn2, WM_SETFONT, (WPARAM)hFont, 0);//设置按钮字体
//修改按钮控件
hBtn3 = CreateWindow(
TEXT("button"), //按钮控件的类名
TEXT("修改"),
WS_CHILD | WS_VISIBLE | WS_BORDER | BS_DEFPUSHBUTTON, //*默认按钮样式*/,
570 /*X坐标*/, 100 /*Y坐标*/, 80 /*宽度*/, 30/*高度*/,
hWnd, (HMENU)3 /*控件唯一标识符*/, hInst, NULL);
SendMessage(hBtn3, WM_SETFONT, (WPARAM)hFont, 0);//设置按钮字体
//查询按钮控件
hBtn4 = CreateWindow(
TEXT("button"), //按钮控件的类名
TEXT("查询"),
WS_CHILD | WS_VISIBLE | WS_BORDER | BS_DEFPUSHBUTTON, //*默认按钮样式*/,
570 /*X坐标*/, 140 /*Y坐标*/, 80 /*宽度*/, 30/*高度*/,
hWnd, (HMENU)4 /*控件唯一标识符*/, hInst, NULL);
SendMessage(hBtn4, WM_SETFONT, (WPARAM)hFont, 0);//设置按钮字体
break;
}
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (wmId)
{
case 1: //按下添加按钮
//INT_PTR back = (INT_PTR)DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG1), hWnd, MyDlgProc);
i= AddItem(hWnd, hListview,vitem,i);
break;
case 2:
//int nSelectItem;
i = DelItem(hWnd, hListview, vitem, i);
break;
case 3:
EditItem(hWnd, hListview, vitem);
break;
case 4:
nSelectIndex = SendMessage(hListview, LVM_GETNEXTITEM, -1, LVNI_SELECTED);//选择数据行数的第二种方法
if (nSelectIndex != -1)
{//判断是否选中一行
//wstrText[4][128] = { 0 };
//通过一个for循环 能够获取第 nSelectIndex item的所有内容
for (n = 0; n < 4; n++)
{
ListView_GetItemText(hListview, nSelectIndex, n, wstrText[n], sizeof(wstrText[n]));
}
wsprintf(szUserInfo, TEXT("姓名:%s\r\n年龄:%s\r\n电话: %s\r\n地址: %s"), wstrText[0], wstrText[1], wstrText[2], wstrText[3]);
MessageBox(hWnd, szUserInfo, TEXT("提示信息"), MB_ICONINFORMATION);
}
else {
MessageBox(hWnd, TEXT("未选择数据,请选择数据!!"), TEXT("提示信息"), MB_ICONINFORMATION);
}
break;
case IDM_ADD: //点击添加
//MessageBox(hWnd, TEXT("添加数据"), TEXT("提示信息"), MB_ICONINFORMATION);
i = AddItem(hWnd, hListview, vitem, i);
break;
case IDM_MOD://点击编辑
// MessageBox(hWnd, TEXT("修改数据"), TEXT("提示信息"), MB_ICONINFORMATION);
EditItem(hWnd, hListview, vitem);
break;
case IDM_DEL://点击删除选项
//MessageBox(hWnd, TEXT("删除数据"), TEXT("提示信息"), MB_ICONINFORMATION);
i = DelItem(hWnd, hListview, vitem, i);
break;
default:
//不处理的消息一定要交给 DefWindowProc 处理。
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
//在listVIEW控件上点击鼠标消息响应。
case WM_NOTIFY: // the message that is being sent always
{
LPNMHDR lpNmhdr = (LPNMHDR)lParam;
//if (lpNmhdr->idFrom == LISTVIEW)
if (lpNmhdr->code == NM_CLICK)// 点击鼠标左键显示所在的行列情况
{
//设置要获取的行列信息
//int iItem = ((LPNMITEMACTIVATE)lParam)->iItem;
//int iSubItem = ((LPNMITEMACTIVATE)lParam)->iSubItem;
// 发送消息获取数据
//ListView_GetItem(lpNmhdr->hwndFrom, &vitem);
// wsprintf(szUserInfo, TEXT("你在列表中点击左键选中了一项,行 %d列 %d"), iItem, iSubItem);
//MessageBox(hWnd, szUserInfo, TEXT("提示信息"), MB_OK | MB_ICONWARNING);
//nSelectItem = ListView_GetSelectionMark(hListview); //获取鼠标选中项的索引
}
if (lpNmhdr->code == NM_RCLICK)// 点击鼠标右键弹出菜单
{
// 1. 获取点击的位置,获取的是相对于桌面的
POINT Point = { 0 };
GetCursorPos(&Point);
// 2. 获取一个子菜单
HMENU hMenu = LoadMenu(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_MENU1));
HMENU hSubMenu = GetSubMenu(hMenu, 0);
// 3. 弹出菜单
TrackPopupMenu(hSubMenu, TPM_LEFTALIGN, Point.x, Point.y, 0, hWnd, NULL);
}
break;
}
case WM_PAINT://窗口绘画:点
{
//int x, xLast;
HDC hdc = BeginPaint(hWnd, &ps);//函数为指定窗口进行绘画作准备,并用将和绘画有关的信息填充到一个 PAINTSTRUCT 结构中。
EndPaint(hWnd, &ps);
return 0;
}
case WM_LBUTTONDOWN:
break;
case WM_MOUSEMOVE://鼠标移动
{
xPos = GET_X_LPARAM(lParam);//鼠标位置X坐标
yPos = GET_Y_LPARAM(lParam);//鼠标位置Y坐标
//不要用LOWORD和HIWORD获取坐标,因为坐标有可能是负的
break;
}
case WM_CLOSE://询问窗口是否关闭
{
if (MessageBox(hWnd, TEXT("要关闭程序吗?"), TEXT("请确认"), MB_YESNO | MB_ICONQUESTION) == IDYES)
{
DestroyWindow(hWnd); //关闭程序
}
else
return 0;//表示处理了此消息,系统不再处理
break;
}
case WM_DESTROY:
{
DeleteObject(hFont);
PostQuitMessage(0);
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// “关于”dialog框的消息处理程序。
INT_PTR CALLBACK MyDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
HWND hLabUsername;
HWND hLabAge;
HWND hLabelDept;
HWND hLabelPost;
static HWND hEditUsername;
static HWND hEditAge;
static HWND hEditDept;
static HWND hEditPost;
int wmId, wmEvent, iUsername, iAge;
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
{
SetWindowPos(hDlg,
HWND_TOP,
200,
200,
0, 0, // Ignores size arguments.
SWP_NOSIZE);
//创建按钮控件
//创建静态文本框控件--用户名
hLabUsername = CreateWindow(TEXT("static"), TEXT("姓名:"),
WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE /*垂直居中*/ | SS_RIGHT /*水平居右*/,
0 /*x坐标*/, 20 /*y坐标*/, 70 /*宽度*/, 26 /*高度*/,
hDlg /*父窗口句柄*/,
(HMENU)11 /*控件ID*/,
hInst /*当前程序实例句柄*/, NULL);
//创建静态文本框控件--密码
hLabAge = CreateWindow(TEXT("static"), TEXT("年龄:"),
WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE /*垂直居中*/ | SS_RIGHT/*水平居右*/,
0, 56, 70, 26,
hDlg, (HMENU)12, hInst, NULL);
//创建单行文本框控件
hEditUsername = CreateWindow(TEXT("edit"), TEXT(""),
WS_CHILD | WS_VISIBLE | WS_BORDER /*边框*/ | ES_AUTOHSCROLL/*水平滚动*/,
80, 20, 200, 25,
hDlg, (HMENU)13, hInst, NULL);
SendMessage(hEditUsername, WM_SETTEXT, 0, (LPARAM)wstrText[0]);
//创建密码输入框
hEditAge = CreateWindow(TEXT("edit"), TEXT(""),
//WS_CHILD | WS_VISIBLE | WS_BORDER | ES_Age /*密码*/ | ES_AUTOHSCROLL /*水平滚动*/,
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL /*水平滚动*/,
80, 56, 200, 25,
hDlg, (HMENU)14, hInst, NULL
);
SetWindowText(hEditAge, wstrText[1]);
//创建静态文本框控件--部门
hLabelDept = CreateWindow(TEXT("static"), TEXT("电话:"),
WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE /*垂直居中*/ | SS_RIGHT /*水平居右*/,
0, 92, 70, 26,
hDlg, (HMENU)15, hInst, NULL);
//创建单行文本框控件
hEditDept = CreateWindow(TEXT("edit"), TEXT(""),
WS_CHILD | WS_VISIBLE | WS_BORDER /*边框*/ | ES_AUTOHSCROLL/*水平滚动*/,
80, 92, 200, 25,
hDlg, (HMENU)16, hInst, NULL);
SetWindowText(hEditDept, wstrText[2]);
hLabelPost = CreateWindow(TEXT("static"), TEXT("地址:"),
WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE /*垂直居中*/ | SS_RIGHT /*水平居右*/,
0, 128, 70, 26,
hDlg, (HMENU)17, hInst, NULL);
//创建单行文本框控件
hEditPost = CreateWindow(TEXT("edit"), TEXT(""),
WS_CHILD | WS_VISIBLE | WS_BORDER /*边框*/ | ES_AUTOHSCROLL/*水平滚动*/,
80, 128, 200, 25,
hDlg, (HMENU)18, hInst, NULL);
SetWindowTextW(hEditPost, wstrText[3]);
//依次设置控件的字体
SendMessage(hLabUsername, WM_SETFONT, (WPARAM)hFont, 0);
SendMessage(hLabAge, WM_SETFONT, (WPARAM)hFont, 0);
SendMessage(hEditUsername, WM_SETFONT, (WPARAM)hFont, 0);
SendMessage(hEditAge, WM_SETFONT, (WPARAM)hFont, 0);
SendMessage(hLabelPost, WM_SETFONT, (WPARAM)hFont, 0);
SendMessage(hLabelDept, WM_SETFONT, (WPARAM)hFont, 0);
SendMessage(hEditPost, WM_SETFONT, (WPARAM)hFont, 0);
SendMessage(hEditDept, WM_SETFONT, (WPARAM)hFont, 0);
break;
}
case WM_COMMAND:
{
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (wmId)
{
case IDOK:
{
GetWindowText(hEditUsername, szUsername, 20);
GetWindowText(hEditAge, szAge, 20);
GetWindowText(hEditDept, szEditDept, 20);
GetWindowText(hEditPost, szEditPost, 20);
StringCchLength(szUsername, 20, &iUsername);
StringCchLength(szAge, 20, &iAge);
// StringCchLength(szUsername, 100, &iUsername);
//StringCchLength(EditPost, 100, &iAge);
if (iUsername <= 0 || iAge <= 0)
{
MessageBox(hDlg, TEXT("输入错误,请信息"), TEXT("信息提示"), MB_ICONINFORMATION);
break;
}
else
{
wsprintf(szUserInfo, TEXT("姓名:%s\r\n年龄:%s\r\n部门: %s\r\n职务: %s"), szUsername, szAge, szEditDept, szEditPost);
MessageBox(hDlg, szUserInfo, TEXT("信息提示"), MB_ICONINFORMATION);
EndDialog(hDlg, wParam);
return (INT_PTR)TRUE;
}
//break;
}
case IDCANCEL:
{
// yprintf(TEXT("dialog cancel clicked"));
//SetWindowText(hwndDlg, TEXT("dialog cancel clicked"));
EndDialog(hDlg, wParam);
return (INT_PTR)FALSE;
}
}
break;
}
/* if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}*/
case WM_DESTROY:
{
EndDialog(hDlg, wParam);
break;
}
}
return (INT_PTR)FALSE; //返回非零值
}
int AddItem(HWND hWnd, HWND hListview,LVITEM vitem,int i)
{
if (DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG1), hWnd, MyDlgProc) == 1)
//dialog窗口内,点击ok 返回值是1,点击cancel返回值为2,这里判断如果点击OK,才对listview添加新的数据
{
int st = check_capacity(&contactlist);
if (st == 1)
{
printf("扩容成功\n");
}
else if (st == -1)
{
printf("扩容失败\n");
}
vitem.mask = LVIF_TEXT;
vitem.iItem = i;//第几行的数据
vitem.iSubItem = 0;//第1列
ListView_InsertItem(hListview, &vitem);
vitem.iSubItem = 1;//第2列
lstrcpy(contactlist.data[i].name, szUsername);
vitem.pszText = contactlist.data[i].name;
ListView_SetItem(hListview, &vitem);
vitem.iSubItem = 2;//第2列
lstrcpy(contactlist.data[i].age, szAge);
vitem.pszText = contactlist.data[i].age;
ListView_SetItem(hListview, &vitem);
vitem.iSubItem = 3;//第3列
lstrcpy(contactlist.data[i].tel, szEditDept);
vitem.pszText = contactlist.data[i].tel;
ListView_SetItem(hListview, &vitem);
vitem.iSubItem = 4;//第4列
lstrcpy(contactlist.data[i].address, szEditPost);
vitem.pszText = contactlist.data[i].address;
ListView_SetItem(hListview, &vitem);
wsprintf(szUserInfo, TEXT("姓名:%s\r\n年龄:%s\r\n部门: %s\r\n职务: %s"), szUsername, szAge, szEditDept, szEditPost);
i++;
contactlist.size++;
save(&contactlist, hWnd,hListview, vitem);
TCHAR buffer[20];
wsprintf(buffer, TEXT("结构数组的大小 %d"), contactlist.size);
MessageBox(hWnd, buffer, TEXT(""), MB_OK);
}
return i;
}