详细说明如下:
我的主窗口中有一个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,而其中内容还未改变时就发出,太灵敏了。所有的问题兜详细解释如上,请指点。

解决方案 »

  1.   

    我是学SDK的,不过没有试过这样的操作。
    我的想法和你一样:既然你的ComboBox是以ListView为父窗口的,那么它的通知消息就应该传递给ListView。但是ListView默认的窗口过程是不处理ComboBox的通知消息的,所以你可能需要将你的ListView进行子类化,然后在子类化的过程中处理这些消息。
    这只是我的设想,供你参考。
      

  2.   

    前辈,我是第二次听到子类化这个词语,你能给我一个关于子类化的例子吗。我的信箱是[email protected]
      

  3.   

    一是子类化ListView,还有一个取巧的办法,告诉你一个诀窍,WM_NOTIFY消息是发往控件创建时设定的父窗口的,以后即使控件的父窗口有变动,这个消息的接收窗口是不会变的。所以你可以在创建ComboBox时指定父窗口是主窗口,然后SetParent为ListView,这样就可以在主窗口里处理了。
      

  4.   

    To:ringphone(临风) ,您的做法实在很有创意,不过我这个问题的子类化还是有点问题,我接触的例子(别的前辈给我的)子类化一般只是同等功能的扩展,比如说,一个OnChar消息,进行字符处理功能的加强。而我需要在我的ListView中创建完combobox后,再将Combobox的消息(这是在ListView中所没有的)在ListView中进行处理。我不知道该在什么消息中进行子类化(加入自己的消息处理函数)。
       还有一个问题,假设我在每差接受到鼠标点击ListView的Item后,进行创建我的Combobox,那么这个combobox的消息感觉就更难处理了.
      

  5.   

    你在ListView中创建完combobox,需要处理Combobox的消息,你既然子类化了ListView,就把ListView当Combobox的父窗口处理啊,响应WM_COMMAND消息就行了。看你的需求,好象每次点击ListView,就创建一个Combobox?那确实要子类化ListView比较方便一点。
      

  6.   

    To:ringphone(临风),多谢您的答案,如果我一开始在创建ListView时就创建一个Combobox,只是不显示(不知道该怎么创建,只是这么想),这时候,我把这个Combobox给子类化了,当我点击ListView的SubItem时,就将这个Combox移动到那里,感觉可行?
      但是这样我还得面对一个问题,就是这个Combobox的EditBox部分将这一列与他相邻的两个SubItem的内容给挡住了。
      而要解决这个问题,需要设置ListView的Item的高度,可是好像不是自画的listView就无法实现?
    请您指点!
      

  7.   

    To:ringphone(临风),前辈,还有一点,我原来只是以为子类化只是截取某个消息,而后对他进行加强功能的处理,现在知道可以将整个创建的窗口进行子类化,也就是这个窗口不论移动到哪里,都可以在子类化后的回调函数中处理。这样我把整个Combobox在创建时就子类化,不知道好不好。
    请您指点!
      

  8.   

    如果我一开始在创建ListView时就创建一个Combobox,只是不显示(不知道该怎么创建,只是这么想),这时候,我把这个Combobox给子类化了,当我点击ListView的SubItem时,就将这个Combox移动到那里,感觉可行?
    ------------------------------------------------
    这是可以的,只要用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));
    这样应该不会挡住下面的了。
      

  9.   

    前辈,我按照您的说法作了,ListView的显示已经没有问题了,
    我创建完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);
    }
      

  10.   

    前辈,您说"处理Combobox的消息需要子类化ListView,在ListView的WM_COMMAND里处理Combobox的用户选择。" 但我发现我子类化Combobox,也能进行处理,只是不知道如何得到中的内容,因为我一点击这个Combobox,他就KILLFOCUS,根本没有给我下拉选择中内容的机会。
      

  11.   

    if(ID_COMBOBOX == wParam)//从来没有进入下面括号内的语句,为何?
    ----------------------------------------
    看看WM_COMMAND的说明,应该是if(ID_COMBOBOX == LOWORD(wParam))
    HIWORD(lParam)里是Combobox的通知消息,CBN_EDITCHANGE之类
      

  12.   

    还有ListView的窗口过程不用处理WM_NOTIFY,应该是主窗口处理
      

  13.   

    手误,上面的HIWORD(lParam)应该是HIWORD(wParam)
      

  14.   

    前辈,我试了一下您的方法,我觉得应该肯定是没有问题的,但是依然没有进入下面的代码       case WM_COMMAND:
               if(ID_COMBOBOX ==LOWORD(wParam))
               lResult =SubComboboxFunc(hWnd, Message,wParam,lParam);而我用您同样的考虑方式子类化Combobox,我发现基本没有问题,只是不知道如何得到中的内容,因为我一点击这个Combobox,他就KILLFOCUS,根本没有给我下拉选择中内容的机会,所以得到的内容永远是第一个条目的。而子类化ListView的问题就一直没有进展!
      

  15.   

    还有一点,您是不是说
    LRESULT CALLBACK SubListViewFunc(HWND hWnd,UINT Message,WPARAM wParam,LONG lParam)中wParam与Message有部分的重复(在消息部分)?
      

  16.   

    我发现一个奇怪的问题:if ( Message ==CBN_DROPDOWN)可以运行下面的代码,换成if ( HIWORD(wParam) == CBN_DROPDOWN)就不对了,而用if ( Message == CBN_SELCHANGE )却是错误的,而用if ( HIWORD(wParam) == CBN_SELCHANGE )反而可以,很无奈。
      

  17.   

    if(ID_LISTVIEW == LOWORD(wParam))与if(ID_LISTVIEW == wParam)很多时候没有区别,晕,问题越来越多。
      

  18.   

    我想知道从combobox中取数,是经过响应无数次消息吗。比如KILLFOCUS消息,在我点击combobox就一直在发生,我想得到下拉后的结果,可是这个消息一开始就把第一个还没有下拉时的条目内容给我了.
      

  19.   

    speedzzx1(试问) ,
    我想知道你这个ID_COMBOBOX是多少,如果这个值超过0xFFFF,那是会有问题,你必须把这个值改小。
      

  20.   

    #define ID_COMBOBOX     104 if (!(hwndCombo = CreateWindowEx (0, 
    TEXT("combobox"), 
    NULL, 
    dwStyle, SubItemRect.left,SubItemRect.top,
    150,/*SubItemRect.right-SubItemRect.left*/
    600,
    g_hwndListView, 
    (HMENU)ID_COMBOBOX, 
    g_hInst, 
    NULL)))
     return NULL;
      

  21.   

    这个问题解决了,是我搞错了,不好意思前辈,我代码改动后把子类化的窗口句柄给错了,您的做法一点都没有错。在此特别感谢。 
      现在就剩下我上面提到的几个小细节问题:我想知道如何从combobox中取数,WM_KILLFOCUS消息,在我点击combobox就一直在发生,我想得到下拉后的结果,可是这个消息一开始就把第一个还没有下拉时的条目内容给我了.  还有一点,您是不是说
    LRESULT CALLBACK SubListViewFunc(HWND hWnd,UINT Message,WPARAM wParam,LONG lParam)中wParam与Message有部分的重复(在消息部分)?这两者(wParam与Message)的消息部分的使用有区别吗?
      

  22.   

    if(ID_COMBOBOX == LOWORD(wParam))
                    {
                    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;
    }
      

  23.   

    LRESULT CALLBACK SubListViewFunc(HWND hWnd,UINT Message,WPARAM wParam,LONG lParam)中wParam与Message有部分的重复(在消息部分)
    ------------------------------------------------------
    没有重复,message是WM_COMMAND的时候,wParam低4位是控件ID,高4位是控件通知消息。lParam是控件句柄
      

  24.   

    我试过了,得到的选项序号永远是第一个,顺便问一句,得到Index后,怎么得到其中的内容?
      

  25.   

    为什么子类化自己(Combobox),得到的选项序号永远是第一个,而用您的做法却没有问题。难道子类化必须是上一级的?