[C++] 纯文本查看 复制代码
// Win32ListCtrl.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "Win32ListCtrl.h"
#include <CommCtrl.h>
#define MAX_LOADSTRING 100
// 全局变量:
HINSTANCE hInst; // 当前实例
TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名
// 此代码模块中包含的函数的前向声明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
// [52]自定义数据
struct OWNER_ITEM
{
TCHAR subItem[3][16]; // 可以用std::string或TCHAR*以获得不定长字符串支持
};
#define ITEM_COUNT 100000
struct OWNER_ITEM g_owner_data[ITEM_COUNT];
HWND g_hListControl = 0;
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// [52]准备数据的时间是无法省略的。可以从文件读取
for (int i = 0; i < ITEM_COUNT; i++)
{
_stprintf_s(g_owner_data[i].subItem[0], 16, _T("%d.col0"), i);
_stprintf_s(g_owner_data[i].subItem[1], 16, _T("%d.col1"), i);
_stprintf_s(g_owner_data[i].subItem[2], 16, _T("%d.col2"), i);
}
// TODO: 在此放置代码。
MSG msg;
HACCEL hAccelTable;
// 初始化全局字符串
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_WIN32LISTCTRL, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32LISTCTRL));
// 主消息循环:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// 函数: MyRegisterClass()
//
// 目的: 注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WIN32LISTCTRL));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WIN32LISTCTRL);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
//
// 函数: InitInstance(HINSTANCE, int)
//
// 目的: 保存实例句柄并创建主窗口
//
// 注释:
//
// 在此函数中,我们在全局变量中保存实例句柄并
// 创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // 将实例句柄存储在全局变量中
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// 函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 目的: 处理主窗口的消息。
//
// WM_COMMAND - 处理应用程序菜单
// WM_PAINT - 绘制主窗口
// WM_DESTROY - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
// [52]创建ListView
case WM_CREATE:
{
g_hListControl = CreateWindow(WC_LISTVIEW, _T(""),
WS_CHILD | WS_VISIBLE | WS_BORDER |
LVS_OWNERDATA | LVS_REPORT | LVS_SHOWSELALWAYS,// [52]设置LVS_OWNERDATA
50, 50,
300, 300,
hWnd,
(HMENU)IDC_LIST_1,
NULL,
NULL);
//整行选择
ListView_SetExtendedListViewStyle(g_hListControl, LVS_EX_FULLROWSELECT); //扩展列表视图样式
LVCOLUMN colInfo_0 = { 0 };
colInfo_0.mask |= LVCF_WIDTH | LVCF_TEXT;
colInfo_0.cx = 100;
colInfo_0.pszText = (LPTSTR)_T("第0列");
SendMessage(g_hListControl, LVM_INSERTCOLUMN, 0, (LPARAM)&colInfo_0); //插入列
LVCOLUMN colInfo_1 = { 0 };
colInfo_1.mask |= LVCF_WIDTH | LVCF_TEXT;
colInfo_1.cx = 100;
colInfo_1.pszText = (LPTSTR)_T("第1列");
SendMessage(g_hListControl, LVM_INSERTCOLUMN, 1, (LPARAM)&colInfo_1);
LVCOLUMN colInfo_2 = { 0 };
colInfo_2.mask |= LVCF_WIDTH | LVCF_TEXT;
colInfo_2.cx = 100;
colInfo_2.pszText = (LPTSTR)_T("第2列");
ListView_InsertColumn(g_hListControl, 2, (LPARAM)&colInfo_2); //插入列
// [52]设置条目总数量
ListView_SetItemCount(g_hListControl, ITEM_COUNT);
}
// [52] 响应WM_NOTIFY
case WM_NOTIFY:
// [52] 区分具体的NOTIFY消息
switch (((LPNMHDR)lParam)->code)
{
case LVN_GETDISPINFO:
// [52]如果多个LIST需要根据ID区分
if (((LPNMHDR)lParam)->idFrom == IDC_LIST_1)
{
NMLVDISPINFO* plvdi = (NMLVDISPINFO*)lParam;
plvdi->item.pszText = g_owner_data[plvdi->item.iItem].subItem[plvdi->item.iSubItem];
return TRUE;
}
break;
case LVN_ODFINDITEM:
if (((LPNMHDR)lParam)->idFrom == IDC_LIST_1)
{
NMLVFINDITEM* pFindInfo = (NMLVFINDITEM*)lParam;
int result = -1;
if ((pFindInfo->lvfi.flags & LVFI_STRING) == 0)
{
return result;
}
int total_count = ListView_GetItemCount(pFindInfo->hdr.hwndFrom);
//这是我们要找的字符串
const TCHAR* searchstr = pFindInfo->lvfi.psz;
DWORD searchLen = _tcslen(searchstr);
int startPos = pFindInfo->iStart;//保存起始位置
//判断是否最后一行
if (startPos >= total_count)
startPos = 0;
int currentPos = startPos;
//开始查找
do
{
if (_tcsnicmp(g_owner_data[currentPos].subItem[0], searchstr, searchLen) == 0)
{
//选中这个元素,停止查找
result = currentPos;
break;
}
currentPos++;
//从头开始
if (currentPos >= total_count)
currentPos = 0;
} while (currentPos != startPos);
return result;
}
break;
}
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
// [52] 修改菜单的“关于”响应,用于测试寻找某条目
case IDM_ABOUT:
{
LVFINDINFO info;
int nIndex;
int total_count = ListView_GetItemCount(g_hListControl);
info.flags = LVFI_PARTIAL | LVFI_STRING;
info.psz = _T("98765");
nIndex = ListView_FindItem(g_hListControl, 0, &info);
if (nIndex != -1)
{
for (int n = nIndex; n < total_count; n++)
{
ListView_EnsureVisible(g_hListControl, n, FALSE);
if (ListView_GetTopIndex(g_hListControl) == nIndex)
break;
}
}
ListView_SetItemState(g_hListControl, nIndex, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
}
// DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: 在此添加任意绘图代码...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}