吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 227|回复: 9
收起左侧

[求助] List Control的使用问题

[复制链接]
董督秀 发表于 2024-10-16 23:36
本帖最后由 董督秀 于 2024-10-20 08:01 编辑

1.如何实现插入并显示近万条索引结果的同时,耗时<1s?网上资料说要可以使用虚拟列表。我试了没成功,如果使用虚拟列表,应该在消息循环里添加什么对应的case消息处理?
目前还没成功使用虚拟列表,导致插入效率较低。在2s左右才能显示结果。

2.如何使得匹配的索引顶行显示而不是在底部显示?
我尝试通过SendMessage匹配索引,但匹配到的索引是在控件底部显示。

3.如何使得匹配到的索引单击一次响应而不是两次?
存在索引匹配到后,需要额外点击别的地方,再单击一次才能显示的这种情况。

问题1.与3.已解决,感谢yes2
问题2.也已完美解决

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

bester 发表于 2024-10-17 11:01
你这个插件接管了ctrl+G吗 还是你保留了原有的功能,然后自己再自定义了一个快捷键?
 楼主| 董督秀 发表于 2024-10-17 11:06
bester 发表于 2024-10-17 11:01
你这个插件接管了ctrl+G吗 还是你保留了原有的功能,然后自己再自定义了一个快捷键?

完全接管OD的Ctrl+G功能。
yes2 发表于 2024-10-17 11:26
参考 https://learn.microsoft.com/zh-cn/cpp/mfc/virtual-list-controls?view=msvc-170
我用MFC测试了一下1万条数据,速度确实很快。
控件设置LVS_OWNERDATA样式,MFC中可以直接在资源界面的属性中修改;
设置预计的数量,这样滚动条会展示正确的范围。m_listCtrl.SetItemCount(10000); m_listCtrl是我定义的控件变量CListCtrl m_listCtrl;
添加LVN_GETDISPINFO响应函数,在MFC中是
ON_NOTIFY(LVN_GETDISPINFO, IDC_LIST1, &CtestListCtrlDlg::OnGetDispInfo)
IDC_LIST1是控件ID,CtestListCtrlDlg是我的对话框类,OnGetDispInfo是自定义的响应函数。
[C++] 纯文本查看 复制代码
void CtestListCtrlDlg::OnGetDispInfo(NMHDR* pNMHDR, LRESULT* pResult)
{
    NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO *>(pNMHDR);
    LVITEM *pItem = &(pDispInfo)->item;

    int iItem = pItem->iItem;

    if (pItem->mask & LVIF_TEXT) //valid text buffer?
    {
        switch (pItem->iSubItem)
        {
        case 0: //fill in main text
            _tcscpy_s(pItem->pszText, pItem->cchTextMax,
                m_Items[iItem].m_strItemText);
            break;
        case 1: //fill in sub item 1 text
            _tcscpy_s(pItem->pszText, pItem->cchTextMax,
                m_Items[iItem].m_strSubItem1Text);
            break;
        case 2: //fill in sub item 2 text
            _tcscpy_s(pItem->pszText, pItem->cchTextMax,
                m_Items[iItem].m_strSubItem2Text);
            break;
        }
    }

    if (pItem->mask & LVIF_IMAGE) //valid image?
    {
        pItem->iImage = m_Items[iItem].m_iImage;
    }
    *pResult = 0;
}

你只需要根据iItem索引,把相关数据设置进去就可以了
 楼主| 董督秀 发表于 2024-10-17 11:32
yes2 发表于 2024-10-17 11:26
参考 https://learn.microsoft.com/zh-cn/cpp/mfc/virtual-list-controls?view=msvc-170
我用MFC测试了一 ...

由于是通过hook完全接管OD的ctrl+g功能,因此不能直接用mfc的消息映射。是通过win32的api,给list control所在的窗体动态设置消息回调。回调是WndProc。现在尝试在回调的wm_notify处理虚拟列表。老哥方便的话,用win32试试...
bester 发表于 2024-10-17 11:38
董督秀 发表于 2024-10-17 11:06
完全接管OD的Ctrl+G功能。

接管的方法方便的时候放一下,我好奇很久了,因为我看很多插件都可以接管系统级的功能,但是我没想到怎么来的
yes2 发表于 2024-10-17 14:41
不能上传zip包可能是会员组权限限制吧,贴上cpp源码凑合看吧。
[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;
}

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
董督秀 + 1 + 1 老哥,看一下下面的回复吧。

查看全部评分

 楼主| 董督秀 发表于 2024-10-17 19:18
yes2 发表于 2024-10-17 14:41
不能上传zip包可能是会员组权限限制吧,贴上cpp源码凑合看吧。
[mw_shl_code=cpp,true]// Win32ListCtrl.c ...

首先谢谢大佬,你提供的代码我单独创建工程并测试了,确实可行。

image.png


但不适合我的情况,我可能没描述清楚。

我的情况是:在项目中添加资源对话框,然后在资源对话框中直接加入现成的List Control。也就是说List Control是资源中已有的控件,并非是API创建的控件。

然后资源对话框的句柄是g_hMainDlg; 资源对话框里的List Control的控件句柄是g_hListControl;

我通过SetWindowLong给资源对话框(g_hMainDlg)动态绑定了消息回调函数WinProc。

然后变量std::set<std::string> g_alllines; 储存了几万行不同内容。

我尝试在消息回调函数WinProc中这样处理:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

        switch (message)
       
                case WM_NOTIFY:
               
                        LPNMHDR nmhdr = reinterpret_cast<LPNMHDR>(lParam);
                        if (nmhdr->hwndFrom == g_hListControl && (nmhdr->code == LVN_GETDISPINFO))
                        {
                        MessageBox(NULL,"123456","123456",0x40);
                        ...

                        // 下面是尝试在List Control中通过虚拟列表的形式显示g_alllines的代码逻辑,使得耗时最短
                        ...

                        }


我发现无论如何都不会执行到MessageBox(NULL,"123456","123456",0x40); ...
yes2 发表于 2024-10-18 11:34
给你个例子。rc里是一个对话框,对话框上一个ListControl,一个Edit,一个Button。
[C++] 纯文本查看 复制代码
// win32DlgListCtrl.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "win32dlglistctrl.h"
#include <CommCtrl.h>

// Global Variables:
HINSTANCE hInst;// current instance
#define ITEM_COUNT  100000
struct OWNER_ITEM
{
    TCHAR subItem[3][16]; // 可以用std::string或TCHAR*以获得不定长字符串支持
};
struct OWNER_ITEM g_owner_data[ITEM_COUNT];

// Forward declarations of functions included in this code module:
BOOL InitInstance(HINSTANCE, int);
INT_PTR CALLBACK Dialog1Proc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPTSTR lpCmdLine,
    int nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);
    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: Place code here.
    MSG msg;

    // Perform application initialization:
    if (!InitInstance(hInstance, nCmdShow))
    {
        return FALSE;
    }

    // Main message loop:
    while (GetMessage(&msg, NULL, 0, 0))
    {
//         if (!IsDialogMessage(msg.hwnd, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int)msg.wParam;
}

//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
    HWND hWnd;

    hInst = hInstance; // Store instance handle in our global variable

    hWnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, Dialog1Proc);

    if (!hWnd)
    {
        return FALSE;
    }

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    return TRUE;
}

// Message handler for dialog1.
INT_PTR CALLBACK Dialog1Proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
    {
        // Initialize the List Control
        HWND hList = GetDlgItem(hDlg, IDC_LIST1);
        SetWindowLong(hList, GWL_STYLE, GetWindowLong(hList, GWL_STYLE) | LVS_OWNERDATA | LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SINGLESEL);
        ListView_SetExtendedListViewStyle(hList, LVS_EX_FULLROWSELECT);
        LVCOLUMN colInfo_0 = { 0 };
        colInfo_0.mask |= LVCF_WIDTH | LVCF_TEXT;
        colInfo_0.cx = 100;
        colInfo_0.pszText = (LPTSTR)_T("第0列");
        ListView_InsertColumn(hList, 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列");
        ListView_InsertColumn(hList, 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(hList, 2, (LPARAM)&colInfo_2);    //插入列
        // [52]设置条目总数量
        ListView_SetItemCount(hList, ITEM_COUNT);
    }
        break;
        // [52] 响应WM_NOTIFY
    case WM_NOTIFY:
        // [52] 区分具体的NOTIFY消息
        switch (((LPNMHDR)lParam)->code)
        {
        case LVN_GETDISPINFO:
            // [52]如果多个LIST需要根据ID区分
            if (((LPNMHDR)lParam)->idFrom == IDC_LIST1)
            {
                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_LIST1)
            {
                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);
                // [52] 重要!!!对话框的WM_NOTIFY返回值要手动通过SetWindowLong设置
                SetWindowLong(hDlg, DWL_MSGRESULT, result);
                return result;
            }
            break;
        }
        break;

    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDOK:
        case IDCANCEL:
            EndDialog(hDlg, LOWORD(wParam));
            PostQuitMessage(0);
            return (INT_PTR)TRUE;
            break;
        case IDC_BUTTON1:
        {
            TCHAR buff[128];
            GetDlgItemText(hDlg, IDC_EDIT1, buff, 128);
            HWND hList = GetDlgItem(hDlg, IDC_LIST1);
            LVFINDINFO info;
            int nIndex;
            int total_count = ListView_GetItemCount(hList);
            nIndex = ListView_GetSelectionMark(hList);
            if (nIndex != -1)
            {
                // [52] 清除当前选中
                ListView_SetItemState(hList, nIndex, 0, LVIS_SELECTED | LVIS_FOCUSED);
            }

            info.flags = LVFI_PARTIAL | LVFI_STRING;
            info.psz = buff;
            nIndex = ListView_FindItem(hList, -1, &info);
            if (nIndex != -1)
            {
                for (int n = nIndex; n < total_count; n++)
                {
                    // [52] 使目标项在最上
                    ListView_EnsureVisible(hList, n, FALSE);
                    if (ListView_GetTopIndex(hList) == nIndex)
                        break;
                }
                // [52] 使目标项选中
                ListView_SetItemState(hList, nIndex, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
            }
        }
            break;
        }

    }
    return (INT_PTR)FALSE;
}

对话框有一点要注意,WM_NOTIFY返回值要手动通过SetWindowLong设置
[C++] 纯文本查看 复制代码
Typically, the dialog box procedure should return TRUE if it processed the message, and FALSE if it did not. If the dialog box procedure returns FALSE, the dialog manager performs the default dialog operation in response to the message.

If the dialog box procedure processes a message that requires a specific return value, the dialog box procedure should set the desired return value by calling SetWindowLong(hwndDlg, DWL_MSGRESULT, lResult) immediately before returning TRUE. Note that you must call SetWindowLong immediately before returning TRUE; doing so earlier may result in the DWL_MSGRESULT value being overwritten by a nested dialog box message.

The following messages are exceptions to the general rules stated above. Consult the documentation for the specific message for details on the semantics of the return value.

免费评分

参与人数 1吾爱币 +2 热心值 +1 收起 理由
董督秀 + 2 + 1 大佬NB!!!完美解决!!!

查看全部评分

 楼主| 董督秀 发表于 2024-10-18 23:08
yes2 发表于 2024-10-18 11:34
给你个例子。rc里是一个对话框,对话框上一个ListControl,一个Edit,一个Button。
[mw_shl_code=cpp,true ...

谢谢大佬。解决了!原来是消息循环的处理不当问题!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-13 05:47

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表