MaxGui: Clear Listbox still broken? (win32)

BlitzMax Forums/BlitzMax Programming/MaxGui: Clear Listbox still broken? (win32)

ModuleInfo "History: 1.16 Release"
ModuleInfo "History: fixed Win32ListBox::clear() to also remove tooltips"

I still get the same bug with the tooltips explained here...
http://www.blitzbasic.com/Community/posts.php?topic=60517

Strict 

Local window:TGadget
Local button:TGadget
Global Listbox:TGadget

Local combobox:TGadget
Local dfa_mode:Int = 0

Const MAXKIDSFOLGEN=29
Const MAXFOLGEN=130

window=CreateWindow("My Window",30,20,200,200)
button=CreateButton("Change Listbox",4,100,100,24,window,BUTTON_OK)

Listbox=CreateListBox(4,4,120,80,window)
Create_Listbox(dfa_mode)


While WaitEvent()
	Select EventID()
		Case EVENT_GADGETACTION
			Print "eventdata="+EventData()
		Case EVENT_WINDOWCLOSE
			End
	End Select

	Select EventSource() 		 
		Case Button 
          dfa_mode=Not dfa_mode
          Create_Listbox(dfa_mode)
	End Select
Wend


Function Create_Listbox(cfg_dfamode:Int)
' Create a fresh Listbox according to dfamode

ClearGadgetItems Listbox ' clean all mess up

Select cfg_dfamode
Case 0
   For Local i:Int=0 To MAXFOLGEN-1
     AddGadgetItem ListBox, "MODE 1 - Item "+i, GADGETITEM_NORMAL, 0, "MODE1 Helptext "+i
   Next 

Case 1
   For Local j:Int=0 To MAXKIDSFOLGEN-1
     AddGadgetItem ListBox, "MODE 2 - Item "+j, GADGETITEM_NORMAL, 0, "MODE2 Helptext "+j
   Next 
End Select 

End Function


Skid, looks like the bug is still there. If you scroll down when you have switched items and hover your mouse over the items, the final part of the tip is broken (e.g. variable j) even though the start (i.e. MODE1/MODE 2) is OK.

Weird....

I have a feeling that for some reason this wasn't going to arrive until a full update, rather than just a syncmods? (No idea why though...)

Mark, it's in the release notes. ELSE I would not have posted this again.

Looking at the Win32 C++ code it appears that the tooltips for listboxs need more work before they are usable.

The main problem is that the item index+1 is used for the toolinfo id. This means inserting items can overwrite an existing id.

The clear listbox is not working as the loop removes item zero each time. As the gadget index is used for the tips it just removes tip 0 many times. The Win32ListBox remove function also is calculating the tip id from index not index+1 as is done in the other functions.

I have also noticed after insert items that the tips can get out of sync after the listbox slider is used.

I deadly need a fix for this.

This was reported a month ago and I hoped it would be easy to fix with my example code provided.

As I don't know C++, I feel kind of helpless. :(

I have made some test changes to win32listbox.cpp. They seem to fix the problems. I still have one bug to hunt down, and some more testing to do.
I will finish this off in the Morning as it is 2:44AM.

I need this to work as well, but it is not a simple fix as it may seem! All the tips need to be moved if inserting or removing them.

Thanks a lot for looking into this!!!

Hopefully fixed, try a syncmods for fix.

Skidracer:
Thanks for the updates!

Your fix uses lParam in the LVITEM structure to store the tip id.
As windows uses lParam for sorting lists, this will stop any Windows API sort on the list items from working. This is a shame as I had just got functions to sort listboxs working.

The fix to this I have written keeps the tips insync with the listbox items when an item is inserted or removed. It does not need lParam.
Do you want me to email a copy to you?

just post here Ziltch, thanks

Here are the modified functions

void Win32ListBox::clear(){
	int count=SendMessage( _gadget.hwnd(),LVM_GETITEMCOUNT,0,0 );
	for (int i=0;i<count;i++){
		remove(0);
	}
}

void Win32ListBox::insert( int index,BBString *item,BBString *tip,int icon ){
	LVITEM it={LVIF_TEXT};
	it.iItem=index;
	it.pszText=cstr(item);
	if( iconStrip() && icon>=0 ){
		it.mask|=LVIF_IMAGE;
		it.iImage=icon;
	}
	SendMessage( _gadget.hwnd(),LVM_INSERTITEM,0,(LPARAM)&it );
	SendMessage(_gadget.hwnd(),LVM_SETCOLUMNWIDTH,0,-1);
	TOOLINFO ti={sizeof(ti)};
	ti.hwnd=_gadget.hwnd();
	ti.uFlags=TTF_SUBCLASS;	
	int i,count,ExistingTip,PriorExistingTip;
	char buffer[8192];
	count=SendMessage( _gadget.hwnd(),LVM_GETITEMCOUNT,0,0 )-1;
    
	// Move tips
	if (index < count) {
		for (i=count;i>index;i--) {
			ti.lpszText=buffer;
			PriorExistingTip = 0;
			ti.uId=i;
			ExistingTip = SendMessage( _tooltips,TTM_GETTOOLINFO,0,(LPARAM)&ti );
			if (i>0) {
				ti.uId=i-1;
				PriorExistingTip = SendMessage( _tooltips,TTM_GETTOOLINFO,0,(LPARAM)&ti );
			}
			ti.uId=i;
			if ((PriorExistingTip==0) && (ExistingTip==1)) {
				SendMessage( _tooltips,TTM_DELTOOL,0,(LPARAM)&ti );
			}
			else if (PriorExistingTip==1) {
				if (ExistingTip==0) {
					ti.uFlags=TTF_SUBCLASS;	
					SendMessage( _tooltips,TTM_ADDTOOL,0,(LPARAM)&ti );
				}
				else {
					SendMessage( _tooltips,TTM_SETTOOLINFO,0,(LPARAM)&ti );  
				}   
			}
		}         
    	} 
    
	ti.uId=index;
	ExistingTip =  SendMessage( _tooltips,TTM_GETTOOLINFO,0,(LPARAM)&ti );
	if (tip->length ) {
		ti.lpszText=cstr(tip);
		ti.rect.left=LVIR_SELECTBOUNDS;
		SendMessage( _gadget.hwnd(),LVM_GETITEMRECT,ti.uId,(LPARAM)&ti.rect );
		if ((ti.uId > count) || (ExistingTip==0)) {
			SendMessage( _tooltips,TTM_ADDTOOL,0,(LPARAM)&ti );
		}
		else {
			SendMessage( _tooltips,TTM_SETTOOLINFO,0,(LPARAM)&ti );  
		}
	}
	else if (ExistingTip==1){
		SendMessage( _tooltips,TTM_DELTOOL,0,(LPARAM)&ti );
	}
}

void Win32ListBox::modify( int index,BBString *item,BBString *tip,int icon ){
	int count ,ExistingTip;
	char buffer[8192];
	LVITEM it={LVIF_TEXT};
	it.iItem=index;
	it.pszText=cstr(item);
	if( iconStrip() && icon>=0 ){
		it.mask|=LVIF_IMAGE;
		it.iImage=icon;
	}
	SendMessage( _gadget.hwnd(),LVM_SETITEM,0,(LPARAM)&it );
	SendMessage(_gadget.hwnd(),LVM_SETCOLUMNWIDTH,0,-1);
	TOOLINFO ti={sizeof(ti)};
	ti.uFlags=TTF_SUBCLASS;
	ti.hwnd=_gadget.hwnd();
	ti.uId=index;
	if (tip->length) {
    	ti.lpszText=buffer;
    	ti.rect.left=LVIR_SELECTBOUNDS;
    	ExistingTip = SendMessage( _tooltips,TTM_GETTOOLINFO,0,(LPARAM)&ti );
	if (ExistingTip==1) {
    	   	SendMessage( _gadget.hwnd(),LVM_GETITEMRECT,index,(LPARAM)&ti.rect );
    		ti.lpszText=cstr(tip);
    		ti.uFlags=TTF_SUBCLASS;	
		SendMessage( _tooltips,TTM_SETTOOLINFO,0,(LPARAM)&ti );
        }
        else {
		ti.lpszText=cstr(tip); 
		SendMessage( _gadget.hwnd(),LVM_GETITEMRECT,index,(LPARAM)&ti.rect );
		SendMessage( _tooltips,TTM_ADDTOOL,0,(LPARAM)&ti );
        }
	}
	else if(ExistingTip==1) {
		SendMessage( _tooltips,TTM_DELTOOL,0,(LPARAM)&ti );
    }
}

void Win32ListBox::remove( int index ){
	int	i,count,ExistingTip ,NextExistingTip ;//(ZIL)
	char buffer[8192];
	count=SendMessage( _gadget.hwnd(),LVM_GETITEMCOUNT,0,0 );
	TOOLINFO ti={sizeof(ti)};
	ti.hwnd=_gadget.hwnd();
	if (index < count-1) {
		// Move tips
		for (i=index;i<count;i++) {
			ti.lpszText=buffer;
			ti.uId=i;
			ExistingTip = SendMessage( _tooltips,TTM_GETTOOLINFO,0,(LPARAM)&ti );
			ti.uId=i+1;
			NextExistingTip= SendMessage( _tooltips,TTM_GETTOOLINFO,0,(LPARAM)&ti );
			ti.uId=i;
			if (NextExistingTip==1) {
				if (ExistingTip==1) {
					SendMessage( _tooltips,TTM_SETTOOLINFO,0,(LPARAM)&ti );
				}
				else {
					SendMessage( _tooltips,TTM_ADDTOOL,0,(LPARAM)&ti );
				}     
			}
			else if (ExistingTip==1) {
				SendMessage( _tooltips,TTM_DELTOOL,0,(LPARAM)&ti );
			}        
		}
	}
	ti.uId=count-1;
	SendMessage( _tooltips,TTM_DELTOOL,0,(LPARAM)&ti );
	SendMessage( _gadget.hwnd(),LVM_DELETEITEM,(WPARAM)index,0 );
	SendMessage(_gadget.hwnd(),LVM_SETCOLUMNWIDTH,0,-1);
}

void Win32ListBox::adjustTips(){
	int i,count;
	char buffer[8192];
	count=SendMessage( _gadget.hwnd(),LVM_GETITEMCOUNT,0,0 );
	for (i=0;i<count;i++) {
		TOOLINFO ti={sizeof(ti)};
		ti.uFlags=TTF_SUBCLASS;
		ti.hwnd=_gadget.hwnd();
		ti.uId=i;
		ti.lpszText=buffer;
		if (SendMessage( _tooltips,TTM_GETTOOLINFO,0,(LPARAM)&ti ))
		{
			ti.rect.left=LVIR_SELECTBOUNDS;
			SendMessage( _gadget.hwnd(),LVM_GETITEMRECT,i,(LPARAM)&ti.rect );
			SendMessage( _tooltips,TTM_SETTOOLINFO,0,(LPARAM)&ti );
		}
	}
}


It looks the indents have got messed up a bit! : Edit fixed code indents

If you use this I can post the sorting code I have worked on.

Thanks

Tooltips are working correctly now. (after sync)

Don't know for the sorting issue though...

Thanks again everyone!

Ziltch, I do intend to incorporate your fix and will bump this thread soon to discuss sorting. Hopefully current fix will suffice for now.