More ListView issues

This is a discussion on More ListView issues within the Windows Programming forums, part of the Platform Specific Boards category; If I move the editbox the ListView creates with the EDITLABELS(?) style, the list item under where it was shows ...

  1. #1
    Registered User
    Join Date
    Jun 2008
    Posts
    161

    More ListView issues

    If I move the editbox the ListView creates with the EDITLABELS(?) style, the list item under where it was shows blank. I tried sending a WM_PAINT to the ListView and UpdateWindow(), but it didn't do anything. Anyone know the right way? Win32 API answers, please. I don't use MFC.

    p.s. What's the easiest way to resize columns based on the font used and length of the longest string in the column? I want everything showing. Maybe I could just set the width of each column based on the width of the listview itself. Then if someone sets the font too big later, it's they're problem. I just want to spread out a bit when the window gets maximized/resized as opposed to everything being pushed against the left side of the box.
    Last edited by Viper187; 06-10-2008 at 01:28 PM.

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,607
    My opinion is still to make your own editbox for all columns. There's no telling how many more issues you'll need to overcome - just to make use of the editbox that the control creates (and expects to modify only the first column).

    You could try calling InvalidateRect() for the area under the editbox, after you move it.

    gg

  3. #3
    Registered User
    Join Date
    Jun 2008
    Posts
    161
    Well, the hard part is already done. I have it setup to edit the right data based on where I click.

    Tried this. Doesn't help. What am I doin wrong?
    Code:
                                if (lvHit.iSubItem) {
                                    RECT lvItemRect; memset(&lvItemRect,0,sizeof(lvItemRect));
                                    lvItemRect.left = LVIR_LABEL;
                                    SendMessage(hListData, LVM_GETITEMRECT, lvItem.iItem, (LPARAM)&lvItemRect);
                                    InvalidateRect(hListData, &lvItemRect, FALSE);
                                    UpdateWindow(hListData);
                                }
    Last edited by Viper187; 06-10-2008 at 01:15 PM.

  4. #4
    Registered User
    Join Date
    Mar 2005
    Location
    Juneda
    Posts
    287
    I know that's not my thread, but when I tested the Viper's code on my last thread [URL="http://cboard.cprogramming.com/showthread.php?t=103936"]http://cboard.cprogramming.com/showthread.php?t=103936[/UR about subitem label edition I done it with 1 row and it worked; ok when I added some more rows it produces that strange effect described here by Viper187.

    Even if I get the first position of the hEditBox on the LVM_BEGINLABELEDIT or on the WM_WINDOWPOSCHANGING in 'newEditProcedure' procedure, and InvalidateRect over the listview control on WM_WINDOWPOSCHANGING, or if I InvalidateRect for the whole listview control, it doesn't reapear the first item on the selected row.

    I have posted that here instead of open a new thread identically to that, and instead waiting in the shadow till someone help on this topic. Sure that won't be bad for both (Viper187 and me, and sure neither for someone else with the same problem ).

    Niara

  5. #5
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,607
    There may not be a solution other than rendering the item text yourself - and that's not much of a solution.

    As far as the ListView knows, its edit box is still sitting on the first column - so you can't really blame it for not re-rendering text that, normally, is sitting behind the edit box that it created. We really don't know what the implementation is doing "under the hood".

    Every ListView, sub-item edit implementation that I've seen creates it's own edit box. I can appreciate the investment of work that's gone into making your current approach workable, but I don't think you'd have to scratch much if you decided to abandon it. From everything that you've had to learn to get where you are now, it shouldn't be too hard to switch approaches. You wouldn't even have to subclass the edit box you create (unless you want it to send out LVN_ENDLABELEDIT like the ListView's does - but that's not required). But hey, you know how to subclass now anyway

    Good luck - keep us updated on your solution.

    gg

  6. #6
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,586
    Out of the box most of the Win32 controls are broken in one way or another or require significant subclassing just to get them to work as they should. ListView is one of these controls. It boggles my mind how much extra work is required to get this control to do anything constructive or useful.

    There are third party libraries available at several sites that have their own ListView implementations as well as flex grid impls. They are a life saver.

  7. #7
    Registered User
    Join Date
    Mar 2005
    Location
    Juneda
    Posts
    287
    If you haven't find any solution (I find lots in VB and MFC, but none in C) you can try that: first some global vars:

    Code:
    HWND llista;//listview
    HWND hlEdit;//a global editlabel box
    WNDPROC prevHLEditProc;//the proc of that edit control
    
    struct _INFOHLEDITBOX//struct for internal information
    {
    HWND phwnd;//main window
    HWND fhwnd;//focused window, not necessary
    LV_ITEM lvi;//item edited
    };
    struct _INFOHLEDITBOX ihleb;//internal information for the hlEdit box
    
    #define HLEBP_ENDLABELEDIT WM_USER+1//message notification equivalent to ENDLABELEDIT

    Here in Cboard there's a thread about how to setup user messages in the right way, I can't remember if was that or not, for the moment this works for me.

    First create the listview without LVS_EDITLABELS but with the fullrow select on. Then create a hidden edit box, setup the internal information and give it the alternative procedure:

    Code:
    llista=CreateWindowEx(WS_EX_CLIENTEDGE,WC_LISTVIEW,"",WS_CHILD|WS_VISIBLE|WS_TABSTOP|LVS_REPORT|LVS_SHOWSELALWAYS|LVS_NOSORTHEADER,0,0,0,0,hwnd,(HMENU)LLISTA_DADES,GetModuleHandle(0),NULL);   
    SendMessage(lt,LVM_FIRST+54,0,32);
    
    hlEdit=CreateWindowEx(0,"EDIT","",WS_CHILD|WS_BORDER|ES_AUTOHSCROLL,0,0,0,0,hwnd,(HMENU)LVEDITBOX,GetModuleHandle(0),NULL);
    SendMessage(hlEdit,WM_SETFONT,(WPARAM)hf1,(LPARAM)MAKELPARAM(TRUE,0));
    prevHLEditProc=(WNDPROC)GetWindowLong(hlEdit,GWL_WNDPROC);
    SetWindowLong(hlEdit,GWL_WNDPROC,(LONG_PTR)hlEditProc);
    ihleb.phwnd=hwnd;
    ihleb.fhwnd=NULL;
    memset(&ihleb.lvi,0,sizeof(ihleb.lvi));
    ihleb.lvi.mask=0;
    ihleb.lvi.iItem=0;
    ihleb.lvi.iSubItem=0;

    Now go to catch the NM_DBLCLK on WM_NOTIFY from the listview, it will be the BEGINLABELEDIT equivalent:

    Code:
    case NM_DBLCLK:
    {
    int i;
    char bff[512];
    LVHITTESTINFO_EX lvHit;
    DWORD dwPos;
    POINT pLoc;
    RECT lvEditRect;
    
    //get the item selected
    i=SendMessage(llista,LVM_GETNEXTITEM,(WPARAM)-1,(LPARAM)LVNI_FOCUSED|LVNI_SELECTED);
    
    //I have a report on the 3 last rows, so I make it noneditable
    if(i<0 || i>=SendMessage(llista,LVM_GETITEMCOUNT,0,0)-3) {break;}
    
    //the same as in your code
    dwPos=GetMessagePos();
    pLoc.x=LOWORD(dwPos);
    pLoc.y=HIWORD(dwPos);
    ScreenToClient(hwnd,&pLoc);
    
    //the same as in your code
    lvHit.pt.x=pLoc.x;
    lvHit.pt.y=pLoc.y;
    lvHit.iItem=i;
    SendDlgItemMessage(hwnd,LLISTA_DADES,LVM_FIRST+57,0,(LPARAM)&lvHit);
    
    //the same as in your code
    lvEditRect.top=lvHit.iSubItem;
    lvEditRect.left=LVIR_LABEL;
    SendDlgItemMessage(hwnd,LLISTA_DADES,LVM_FIRST+56,i,(LPARAM)&lvEditRect);
    
    //setup the internal information for the label editing
    memset(&ihleb.lvi,0,sizeof(ihleb.lvi));
    ihleb.fhwnd=NULL;//you can delete it from here and from the struct
    ihleb.lvi.mask=LVIF_TEXT;
    ihleb.lvi.iItem=i;
    ihleb.lvi.iSubItem=lvHit.iSubItem;
    ihleb.lvi.pszText=bff;
    ihleb.lvi.cchTextMax=sizeof(bff);
    SendMessage(llista,LVM_GETITEM,0,(LPARAM)&ihleb.lvi);
    
    //set the initial text to the edit
    SendMessage(hlEdit,WM_SETTEXT,0,(LPARAM)bff);
    //and show/focuse it
    SetWindowPos(hlEdit,HWND_TOP,lvEditRect.left,lvEditRect.top+1,(lvEditRect.right-lvEditRect.left),(lvEditRect.bottom-lvEditRect.top)+2,SWP_SHOWWINDOW);
    SetFocus(hlEdit);
    }
    break;

    The next is to set the alternative procedure, like that:

    Code:
    LRESULT CALLBACK hlEditProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
    {
    switch(msg)
        {
        case WM_KILLFOCUS:
            {
            ihleb.fhwnd=(HWND)wParam;//not necessary
            //this is the end label editing state, so hide the box and inform the parent
            SetWindowPos(hlEdit,HWND_BOTTOM,0,0,0,0,SWP_HIDEWINDOW);
            SendMessage(ihleb.phwnd,HLEBP_ENDLABELEDIT,0,0);
            return 0;
            }
        break;
        }
    return CallWindowProc(prevHLEditProc,hwnd,msg,wParam,lParam);
    }


    Finally evalue the HLEBP_ENDLABELEDIT message on the main window proc as it be the ENDLABELEDIT:

    Code:
    case HLEBP_ENDLABELEDIT:
            {
            char bff[512];
            //get the new text
            SendMessage(hlEdit,WM_GETTEXT,(WPARAM)sizeof(bff),(LPARAM)bff);
            /setup the new item text, don't modify the item index
            ihleb.lvi.pszText=bff;
            ihleb.lvi.cchTextMax=strlen(bff);
            SendMessage(llista,LVM_SETITEM,0,(LPARAM)&ihleb.lvi);
            }
        break;

    Just make some more implementations like the escape or return key press to quit the label editing.


    I'm sure that can be done in a better way, or in a most elegant way; but for the moment hope that helps.

    Niara

  8. #8
    Registered User
    Join Date
    Jun 2008
    Posts
    161
    I'm not really bothered enough by the text being temporarily missing to redo everything. I have too much other stuff to add.

  9. #9
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    Quote Originally Posted by Bubba View Post
    Out of the box most of the Win32 controls are broken in one way or another or require significant subclassing just to get them to work as they should. ListView is one of these controls. It boggles my mind how much extra work is required to get this control to do anything constructive or useful.

    There are third party libraries available at several sites that have their own ListView implementations as well as flex grid impls. They are a life saver.
    Indeed. Lately I've been writing my own custom controls for most of my things. It indeed is quite a lot of extra work, but the result is that much better (sometimes also because those controls are available only for wrappers). The controls are optimized for the job and are using the raw buffers of the data they are supposed to show instead of "middle man" buffers.
    "The Internet treats censorship as damage and routes around it." - John Gilmore

  10. #10
    Registered User
    Join Date
    Jun 2008
    Posts
    161
    Is anyone familiar with the messages the control is supposed to handle when it's told to repaint/redraw? If we knew how to do it manually, I could just add it to the control's procedure and override the default handling (or lack thereof) of said messages. I already have it subclased. I just don't have a clue how to repaint/draw something. I doubt just grabbing the WM_PAINT message and returning TRUE/FALSE would do it, would it?
    Last edited by Viper187; 06-12-2008 at 10:48 AM.

  11. #11
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,607
    >> If we knew how to do it manually, I could just add it to the control's procedure and override the default handling (or lack thereof) of said messages
    Don't you think the amount of effort to get your approach to work nicely is becoming more than it's worth?
    Niara is already up and running creating edit boxes....

    >> Is anyone familiar with the messages the control is supposed to handle...
    If I were going to brute force it - I'd just get a bitmap if the item's cell before the edit box is created and moved - then you can just put the bitmap back after moving the edit box.

    gg

  12. #12
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,855
    As pointed out by CodePlug, your appraoch is wrong.

    IMO you are now digging the hole deeper to fix that original design 'choice'.

    Quote Originally Posted by Viper187 View Post
    Is anyone familiar with the messages the control is supposed to handle when it's told to repaint/redraw? If we knew how to do it manually, I could just add it to the control's procedure and override the default handling (or lack thereof) of said messages. I already have it subclased. I just don't have a clue how to repaint/draw something. I doubt just grabbing the WM_PAINT message and returning TRUE/FALSE would do it, would it?
    Set the LV to Owner Draw. Not easy, espeacially if you are having issues with this.

    If you Owner Draw you will have to handle ALL drawing, including all text.

    As the LV has one DC for the whole control you have to find the area to draw the text by adding all the rows and cols areas together.

    If you do not get it right the LV will flicker, shear text, display the wrong or no text, not scroll properly etc.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  13. #13
    Registered User
    Join Date
    Jun 2008
    Posts
    161
    Well, I changed to an edit box of my own creation. We'll see how it works. Thanks for the sample, Niara.

  14. #14
    Registered User
    Join Date
    Mar 2005
    Location
    Juneda
    Posts
    287
    Hi glad to help

    Here maybe there's two ways to find a solution: as Bubba say get a third party library, surelly it will be more complete and error-free than whatever I can do (in my case), so really that can be a life saver; but by the other hand as maxorator says those libraries will be for standard use, so custom controls can be more optimized for the work. I suppose that sometimes the solution is to get a free library and sometimes to make a custom control.

    Niara

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. ListView Refresh, Update
    By de4th in forum C++ Programming
    Replies: 1
    Last Post: 12-23-2006, 08:13 AM
  2. Replies: 6
    Last Post: 07-10-2006, 12:05 AM
  3. Troubles with ListView and Toolbar
    By cornholio in forum Windows Programming
    Replies: 8
    Last Post: 11-14-2005, 12:26 AM
  4. Listview with c/c++
    By X PaYnE X in forum Windows Programming
    Replies: 8
    Last Post: 03-20-2005, 10:29 PM
  5. Listview??
    By SuperNewbie in forum C# Programming
    Replies: 4
    Last Post: 02-13-2003, 02:34 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21