详细说明如下:
我的主窗口中有一个ListView,那么我根据主窗口是否有变化,并判断是不是ListView引起。而后根据不同的消息进行不同的处理,如下:
LRESULT CALLBACK MainWndProc( HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{.............
case WM_NOTIFY: //如果MainWnd有变化
if(ID_LISTVIEW == wParam)//并且是ListView引起
{
lResult = OnListViewNotify(hwnd, lParam);//处理这个ListView引起的消息lParam
}也就是说,这些消息的处理必须放到控件的父窗口进行处理。
而现在,我在ListView的一个subItem的位置建立了一个combobox,如下:
LRESULT OnListViewNotify( HWND hwnd,LPARAM lParam)
{
NMHDR* pnmh = (NMHDR*) lParam;
LRESULT lResult = 0;
NMLVDISPINFO *pLVdi;
case LVN_ITEMACTIVATE://当我点击某一行时
..........................//得到行的信息,比如高度,列数,此处略去
if(IsCombo(col))//如果是需要画combobox的那一列
{
if (!(hwndCombo = CreateWindowEx (0, TEXT("combobox"),NULL,
dwStyle, SubItemRect.left,SubItemRect.top,
150,600,g_hwndListView, (HMENU)ID_COMBOBOX, g_hInst, NULL)))
return NULL;
// // Add 10 items to the combo box.//下面是给这个combobox加入10个item.
现在的问题就是,如果我的这个combobox有消息发生,那么应该是在他的父窗口接受并处理,但是他的父窗口ListView(g_hwndListView)建立时和mainWnd不同,没有回调函数,主要是没有带lparam这个参数,试过用 LVN_ITEMCHANGED:来进行处理,但是这个消息会在点击ListView,而其中内容还未改变时就发出,太灵敏了。所有的问题兜详细解释如上,请指点。
我的主窗口中有一个ListView,那么我根据主窗口是否有变化,并判断是不是ListView引起。而后根据不同的消息进行不同的处理,如下:
LRESULT CALLBACK MainWndProc( HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{.............
case WM_NOTIFY: //如果MainWnd有变化
if(ID_LISTVIEW == wParam)//并且是ListView引起
{
lResult = OnListViewNotify(hwnd, lParam);//处理这个ListView引起的消息lParam
}也就是说,这些消息的处理必须放到控件的父窗口进行处理。
而现在,我在ListView的一个subItem的位置建立了一个combobox,如下:
LRESULT OnListViewNotify( HWND hwnd,LPARAM lParam)
{
NMHDR* pnmh = (NMHDR*) lParam;
LRESULT lResult = 0;
NMLVDISPINFO *pLVdi;
case LVN_ITEMACTIVATE://当我点击某一行时
..........................//得到行的信息,比如高度,列数,此处略去
if(IsCombo(col))//如果是需要画combobox的那一列
{
if (!(hwndCombo = CreateWindowEx (0, TEXT("combobox"),NULL,
dwStyle, SubItemRect.left,SubItemRect.top,
150,600,g_hwndListView, (HMENU)ID_COMBOBOX, g_hInst, NULL)))
return NULL;
// // Add 10 items to the combo box.//下面是给这个combobox加入10个item.
现在的问题就是,如果我的这个combobox有消息发生,那么应该是在他的父窗口接受并处理,但是他的父窗口ListView(g_hwndListView)建立时和mainWnd不同,没有回调函数,主要是没有带lparam这个参数,试过用 LVN_ITEMCHANGED:来进行处理,但是这个消息会在点击ListView,而其中内容还未改变时就发出,太灵敏了。所有的问题兜详细解释如上,请指点。
我的想法和你一样:既然你的ComboBox是以ListView为父窗口的,那么它的通知消息就应该传递给ListView。但是ListView默认的窗口过程是不处理ComboBox的通知消息的,所以你可能需要将你的ListView进行子类化,然后在子类化的过程中处理这些消息。
这只是我的设想,供你参考。
还有一个问题,假设我在每差接受到鼠标点击ListView的Item后,进行创建我的Combobox,那么这个combobox的消息感觉就更难处理了.
但是这样我还得面对一个问题,就是这个Combobox的EditBox部分将这一列与他相邻的两个SubItem的内容给挡住了。
而要解决这个问题,需要设置ListView的Item的高度,可是好像不是自画的listView就无法实现?
请您指点!
请您指点!
------------------------------------------------
这是可以的,只要用CreateWindow创建Combobox时指定父窗口为ListView,然后ShowWindow把Combobox隐藏起来。
主窗口WM_NOTIFY到点击ListView时,SetWindowPos把Combobox到SubItemRect坐标,Show出来。
处理Combobox的消息需要子类化ListView,在ListView的WM_COMMAND里处理Combobox的用户选择。Combobox的EditBox部分将相邻的两个SubItem的内容给挡住的问题:
可以改变Combobox的宽度,但无法控制高度,但是你可以把Combobox的字体设置成与ListView相同,
HFONT hf = (HFONT)SendMessage(hWndListView,WM_GETFONT,0,0);
SendMessage(hWndCombobox,WM_SETFONT,(WPARAM)hf,MAKELPARAM(TRUE,0));
这样应该不会挡住下面的了。
我创建完ListView以后,就将其子类化如下:
lpfnOldListViewProc = (WNDPROC)SetWindowLong(g_hwnd,GWL_WNDPROC, (DWORD)SubListViewFunc);并且在ListView中创建了我的Combobox。而后,在子类化函数中按照您的说法进行处理:
LRESULT CALLBACK SubListViewFunc(HWND hWnd,UINT Message,WPARAM wParam,LONG lParam)
{
long lResult = 0;
switch(Message)
{
case WM_COMMAND:
if(ID_COMBOBOX == wParam)//从来没有进入下面括号内的语句,为何?
{
lResult =SubComboboxFunc(hWnd, Message,wParam,lParam);
}
break;
case WM_NOTIFY://显示ListView
lResult = OnListViewNotify(g_hwnd, lParam);
break;
}
return CallWindowProc(lpfnOldListViewProc, hWnd, Message, wParam,
lParam);
}
----------------------------------------
看看WM_COMMAND的说明,应该是if(ID_COMBOBOX == LOWORD(wParam))
HIWORD(lParam)里是Combobox的通知消息,CBN_EDITCHANGE之类
if(ID_COMBOBOX ==LOWORD(wParam))
lResult =SubComboboxFunc(hWnd, Message,wParam,lParam);而我用您同样的考虑方式子类化Combobox,我发现基本没有问题,只是不知道如何得到中的内容,因为我一点击这个Combobox,他就KILLFOCUS,根本没有给我下拉选择中内容的机会,所以得到的内容永远是第一个条目的。而子类化ListView的问题就一直没有进展!
LRESULT CALLBACK SubListViewFunc(HWND hWnd,UINT Message,WPARAM wParam,LONG lParam)中wParam与Message有部分的重复(在消息部分)?
我想知道你这个ID_COMBOBOX是多少,如果这个值超过0xFFFF,那是会有问题,你必须把这个值改小。
TEXT("combobox"),
NULL,
dwStyle, SubItemRect.left,SubItemRect.top,
150,/*SubItemRect.right-SubItemRect.left*/
600,
g_hwndListView,
(HMENU)ID_COMBOBOX,
g_hInst,
NULL)))
return NULL;
现在就剩下我上面提到的几个小细节问题:我想知道如何从combobox中取数,WM_KILLFOCUS消息,在我点击combobox就一直在发生,我想得到下拉后的结果,可是这个消息一开始就把第一个还没有下拉时的条目内容给我了. 还有一点,您是不是说
LRESULT CALLBACK SubListViewFunc(HWND hWnd,UINT Message,WPARAM wParam,LONG lParam)中wParam与Message有部分的重复(在消息部分)?这两者(wParam与Message)的消息部分的使用有区别吗?
{
lResult =SubComboboxFunc(hWnd, Message,wParam,lParam);
}
break;这个SubComboboxFunc(hWnd, Message,wParam,lParam);不知道你是怎么写的,看起来象是窗口过程,
你并不需要子类化ComboBox,按你现在的代码,这个SubComboboxFunc应该这么写,如果这个函数仅在这个WM_COMMAND里面调用的话:
LRESULT SubComboboxFunc(hWnd, Message,wParam,lParam)
{
if(HIWORD(wParam) == CBN_SELCHANGE)
{
//得到选项序号
int index = SendMessage((HWND)lParam,CB_GETCURSEL,0,0);
//继续其他操作...
}
return 0;
}
------------------------------------------------------
没有重复,message是WM_COMMAND的时候,wParam低4位是控件ID,高4位是控件通知消息。lParam是控件句柄