PlanetSquires Forums

Support Forums => Other Software and Code => Topic started by: Haakon Birkeland on August 15, 2006, 11:22:23 PM

Title: Find Cell location and size
Post by: Haakon Birkeland on August 15, 2006, 11:22:23 PM
Hi there

I have been translating a program I wrote using EZGUI to FireFly. A function I can't seem to translate is EZ_GetLVClickInfo which would give me the position and size of the cell I clicked in. I would then superimpose a properly sized textbox over the cell making it look like a grid.
Does anybody have a method of finding the cell and it's size?
Tried using the API but it's like chinese with English words

thanx
bert
Title: Find Cell location and size
Post by: Roger Garstang on August 16, 2006, 01:39:02 AM
This can be done as I've done it with FireFly using a ListView which from the EZGUI name looks like what he is using.  Looks like his function just pulled data from the Notification message of the ListView.  I don't have my code in front of me, but I believe I did it that way too, or used a ListView API function to get the bounds of the cell.  Usually takes a 1-3 pixel adjustment too since the control placing in the grid has borders and such, but it can look pretty sharp, and FireFly made it really easy.  I was able to use Combos and Edit/Text boxes.

Look for LVM_ messages like LVM_GETITEMRECT in google, and it will usually find the MSDN help and you'll then see a whole list of other commands to get column and row sizes, etc in the left sidebar.
Title: Find Cell location and size
Post by: TechSupport on August 16, 2006, 09:06:59 AM
Here is a quick example.... based somewhat on the code posted at: http://www.planetsquires.com/forums/viewtopic.php?t=1764

FireFly 3 will have substantially improved ListView and TreeView support.

Notice that I use a PostMessage in the LVM_ITEMCHANGING because we don't want to get into an endless loop by updating text during that message.


%MSG_USER_ENDLISTVIEWEDIT = %WM_USER + 100

Type LISTVIEW_TEXTEDIT
  hTextBox As Dword
  nRow     As Long
  nCol     As Long
End Type  
Global gListviewEdit As LISTVIEW_TEXTEDIT
       
       
'------------------------------------------------------------------------------------------------------------------------
Function FORM1_WM_CREATE ( _
                        hWndForm As Dword, _  ' handle of Form
                        ByVal UserData As Long _  'optional user defined Long value
                        ) As Long

  FF_ListView_DeleteAllItems HWND_FORM1_LISTVIEW1
     
  FF_ListView_InsertColumn HWND_FORM1_LISTVIEW1, 0, "Column1", 0, 100
  FF_ListView_InsertColumn HWND_FORM1_LISTVIEW1, 1, "Column2", 0, 100
  FF_ListView_InsertColumn HWND_FORM1_LISTVIEW1, 2, "Column3", %LVCFMT_RIGHT, 100
     
     
  For row& = 0 To 10
     For col& = 0 To 2
         FF_ListView_InsertItem HWND_FORM1_LISTVIEW1, row&, col&, Str$(row&) & Str$(col&), 0, 0
     Next
  Next

End Function


'------------------------------------------------------------------------------------------------------------------------
Function FORM1_CUSTOM (hWndForm As Dword, wMsg As Long, wParam As Dword, lParam As Long) As Long
  Local pNmLvw       As NM_LISTVIEW Ptr
  Local lLvItem      As Long
  Local lLvSubItem   As Long
  Local rectSub      As Rect  
  Local lEditRow     As Long
  Local lEditCol     As Long
  Local hEdit        As Dword
  Local strTextCell  As String
 
  Select Case wMsg
      Case %WM_NOTIFY
          Select Case LoWrd(wParam)
              Case IDC_FORM1_LISTVIEW1
                  pNmLvw = lParam
                  If (@pNmLvw.hdr.code = %NM_DBLCLK) And (@pNmLvw.iItem > -1) Then ' doubleclick in listview
                      lLvItem     = @pNmLvw.iItem
                      lLvSubItem  = @pNmLvw.iSubItem
                     
                      ' Act on the column doubleclicked
                      Select Case lLvSubItem
                          Case 0
                           MsgBox "Column 0 locked"
                       Case 1
                           GoSub EditCell
                       Case 2
                           MsgBox "Column 2 locked"
                     End Select
                 End If
          End Select
 
 
      Case %MSG_USER_ENDLISTVIEWEDIT
         CancelListviewEdit
         
 End Select


Exit Function

EditCell:

  lEditRow = lLvItem
  lEditCol = lLvSubItem

   ' Is the cell selected
   If IsTrue(ListView_GetItemState(HWND_FORM1_LISTVIEW1, lEditRow, %LVIS_SELECTED)) Then
                     
       ' get the rect of the subitem
       ListView_GetSubItemRect HWND_FORM1_LISTVIEW1, lEditRow, lEditCol, %LVIR_LABEL, VarPtr(rectSub)                
           
       'prüfen ob bereits ein hEdit besteht
       If IsWindow(gListviewEdit.hTextBox) Then DestroyWindow(gListviewEdit.hTextBox)
                     
       ' Save the cell info
       gListviewEdit.nRow = lEditRow
       gListviewEdit.nCol = lEditCol

        ' Create the Edit1 edit control
       gListviewEdit.hTextBox = CreateWindowEx( %WS_EX_LEFT, _                                        ' extended styles
                                "Edit", _                                            ' class name
                                "", _                                                ' caption
                                %WS_CHILD Or %WS_VISIBLE Or %ES_LEFT Or %ES_AUTOHSCROLL Or %ES_NOHIDESEL , _         ' class styles
                                rectSub.nLeft + 6, rectSub.nTop, _               ' left, top
                                rectSub.nRight - rectSub.nLeft, rectSub.nBottom - rectSub.nTop, _   ' width, height
                                HWND_FORM1_LISTVIEW1, 9999, _                                 ' handle of parent, control ID
                                GetModuleHandle(ByVal %Null), ByVal %Null)           ' handle of instance, creation parameters
                                                                                                                                                           
     'setze Font für EditControl
     SendMessage gListviewEdit.hTextBox, %WM_SETFONT, GetStockObject(%DEFAULT_GUI_FONT), %TRUE
                       
     ShowWindow gListviewEdit.hTextBox, %SW_SHOWNORMAL
     SetFocus gListviewEdit.hTextBox

     'Text aus Listview Zelle in EditControl
     strTextCell = FF_ListView_GetItemText (HWND_FORM1_LISTVIEW1, lEditRow, lEditCol)
     FF_TextBox_SetText gListviewEdit.hTextBox, strTextCell
     FF_TextBox_SetSel gListviewEdit.hTextBox, 0, -1
     
     
  End If
 
  Return

End Function



'------------------------------------------------------------------------------------------------------------------------
Function FORM1_LISTVIEW1_LVN_ITEMCHANGING ( _
                                         ControlIndex  As Long,            _  ' index in Control Array
                                         hWndForm      As Dword,           _  ' handle of Form
                                         hWndControl   As Dword,           _  ' handle of Control
                                         ByVal lpNMV   As NM_LISTVIEW Ptr  _  ' pointer to NM_LISTVIEW
                                         ) As Long

  ' Cancel any edit of a Listview label
  PostMessage hWndForm, %MSG_USER_ENDLISTVIEWEDIT, 0, 0
 
     
End Function



'------------------------------------------------------------------------------------------------------------------------
Function CancelListviewEdit() As Long
 
  Local sText        As String
 
  If gListviewEdit.hTextBox = 0 Then Exit Function
 
  ' If the Listview's editing textbox exists then we
  ' need to get its text and update the Listview and then destroy it.
  sText = FF_TextBox_GetText( gListviewEdit.hTextBox )
  FF_ListView_SetItemText HWND_FORM1_LISTVIEW1, gListviewEdit.nRow, gListviewEdit.nCol, sText
 
  DestroyWindow gListviewEdit.hTextBox
  gListviewEdit.hTextBox = 0
 
End Function
Title: Find Cell location and size
Post by: Roger Garstang on August 16, 2006, 05:34:34 PM
Same question...almost a year before???   Looks like more work than I did in my code, but it'll work.  I'll post mine if I can find it.
Title: Find Cell location and size
Post by: Haakon Birkeland on August 16, 2006, 09:15:34 PM
It is the same question. Just never could get the code working properly with my program. I seemed to work the first time then go somewhere in deep space. Lack of time and understanding how the code worked, I ended up leaving the project on the shelf. Now back at trying it again.
With the extra code maybe it will work for me. I am just not very good when it comes down to events. Can't get away from linear thinking.

Bert
Title: Find Cell location and size
Post by: TechSupport on August 16, 2006, 10:07:48 PM
Quote from: mercierbI am just not very good when it comes down to events. Can't get away from linear thinking.
I hear you loud and clear! I had a hell of time trying to get out of that mode of thinking. Wow! It seemed to take forever and then one day it "just clicked" (get it? "clicked", ha ha ha ha).  :)  Seriously, it takes a different way of thinking realizing that anything can happen at anytime. Scary really. ;)
Title: Find Cell location and size
Post by: Haakon Birkeland on August 17, 2006, 12:07:59 AM
Believe me, it hasn't clicked with me.
Now for another stupid question.
How would I access the events like WM_CHAR of that new edit control?

I want to intercept the Enter key to terminate the edit and give the focus to another part of the program.

Bert
Title: Find Cell location and size
Post by: TechSupport on August 17, 2006, 12:14:41 AM
I am about ready to go to bed... I'll round up an example in the morning.

The best way to handle this would be to create a TextBox on your Form and set its WS_VISIBLE to False. Move that TextBox into place on your ListView and the show it. When you're finished with the TextBox, HIDE it rather than DESTROY it. Using a Firefly created TextBox allows you to respond to the WM_CHAR messages because FireFly automatically subclasses the TextBox for you. You can subclass the TextBox yourself but it is a little more work.

I'll post an example of what I mean as soon as I can.
Title: Find Cell location and size
Post by: Haakon Birkeland on August 17, 2006, 12:21:29 AM
Goodnight forgot how late it would be in Newfoundland

thanx
again
Title: Find Cell location and size
Post by: TechSupport on August 17, 2006, 11:06:49 AM
Below is the code. It is fairly easy to do with FireFly. The editing is finished when the %VK_RETURN or %VK_ESCAPE keys are triggered in the WM_KEYUP message.

You will need to add a TextBox to your Form (name it "txtListviewEdit") and set the following properties:
WS_VISIBLE unchecked
WS_EX_CLIENTEDGE unchecked
SelText = True


%MSG_USER_ENDLISTVIEWEDIT = %WM_USER + 100

Type LISTVIEW_TEXTEDIT
  hTextBox As Dword
  nRow     As Long
  nCol     As Long
End Type    
Global gListviewEdit As LISTVIEW_TEXTEDIT
       
       
'------------------------------------------------------------------------------------------------------------------------
Function FORM1_WM_CREATE ( _
                        hWndForm As Dword, _  ' handle of Form
                        ByVal UserData As Long _  'optional user defined Long value
                        ) As Long

  FF_ListView_DeleteAllItems HWND_FORM1_LISTVIEW1
     
  FF_ListView_InsertColumn HWND_FORM1_LISTVIEW1, 0, "Column1", 0, 100
  FF_ListView_InsertColumn HWND_FORM1_LISTVIEW1, 1, "Column2", 0, 100
  FF_ListView_InsertColumn HWND_FORM1_LISTVIEW1, 2, "Column3", %LVCFMT_RIGHT, 100
     
     
  For row& = 0 To 10
     For col& = 0 To 2
         FF_ListView_InsertItem HWND_FORM1_LISTVIEW1, row&, col&, Str$(row&) & Str$(col&), 0, 0
     Next
  Next
 
End Function


'------------------------------------------------------------------------------------------------------------------------
Function FORM1_CUSTOM (hWndForm As Dword, wMsg As Long, wParam As Dword, lParam As Long) As Long
  Local pNmLvw       As NM_LISTVIEW Ptr
  Local lLvItem      As Long
  Local lLvSubItem   As Long
  Local rectSub      As Rect  
  Local lEditRow     As Long
  Local lEditCol     As Long
  Local hEdit        As Dword
  Local strTextCell  As String
   
  Select Case wMsg
      Case %WM_NOTIFY
          Select Case LoWrd(wParam)
              Case IDC_FORM1_LISTVIEW1
                  pNmLvw = lParam
                  If (@pNmLvw.hdr.code = %NM_DBLCLK) And (@pNmLvw.iItem > -1) Then ' doubleclick in listview
                      lLvItem     = @pNmLvw.iItem
                      lLvSubItem  = @pNmLvw.iSubItem
                       
                      ' Act on the column doubleclicked
                      Select Case lLvSubItem
                          Case 0
                           MsgBox "Column 0 locked"
                       Case 1
                           GoSub EditCell
                       Case 2
                           MsgBox "Column 2 locked"
                     End Select
                 End If
          End Select
 
 
      Case %MSG_USER_ENDLISTVIEWEDIT
         CancelListviewEdit
         
 End Select


Exit Function

EditCell:

  lEditRow = lLvItem
  lEditCol = lLvSubItem

   ' Is the cell selected
   If IsTrue(ListView_GetItemState(HWND_FORM1_LISTVIEW1, lEditRow, %LVIS_SELECTED)) Then
                     
       ' get the rect of the subitem
       ListView_GetSubItemRect HWND_FORM1_LISTVIEW1, lEditRow, lEditCol, %LVIR_LABEL, VarPtr(rectSub)                
           
       ' Save the cell info
       gListviewEdit.hTextBox = HWND_FORM1_TXTLISTVIEWEDIT
       gListviewEdit.nRow     = lEditRow
       gListviewEdit.nCol     = lEditCol

       ' Get the text from the Listview cell and place it in the textBox
       strTextCell = FF_ListView_GetItemText (HWND_FORM1_LISTVIEW1, lEditRow, lEditCol)
       FF_TextBox_SetText gListviewEdit.hTextBox, strTextCell
       FF_TextBox_SetSel gListviewEdit.hTextBox, 0, -1
       
       ' Move the TextBox into position.
       ' Recalculate the Listview cell position based on coordinates of the Form. This
       ' saves us from having to make the TextBox the child of the Listview.
       MapWindowPoints HWND_FORM1_LISTVIEW1, HWND_FORM1, rectSub, 2
       SetWindowPos gListviewEdit.hTextBox, %HWND_TOP, _
                    rectSub.nLeft + 6, rectSub.nTop, _
                    rectSub.nRight - rectSub.nLeft, rectSub.nBottom - rectSub.nTop, _  
                    %SWP_SHOWWINDOW
       
       SetFocus gListviewEdit.hTextBox
       
  End If
   
  Return

End Function



'------------------------------------------------------------------------------------------------------------------------
Function FORM1_LISTVIEW1_LVN_ITEMCHANGING ( _
                                         ControlIndex  As Long,            _  ' index in Control Array
                                         hWndForm      As Dword,           _  ' handle of Form
                                         hWndControl   As Dword,           _  ' handle of Control
                                         ByVal lpNMV   As NM_LISTVIEW Ptr  _  ' pointer to NM_LISTVIEW
                                         ) As Long

  ' Cancel any edit of a Listview label
  PostMessage hWndForm, %MSG_USER_ENDLISTVIEWEDIT, 0, 0
   
     
End Function



'------------------------------------------------------------------------------------------------------------------------
Function CancelListviewEdit() As Long
   
  Local sText        As String
   
  If gListviewEdit.hTextBox = 0 Then Exit Function
   
  ' If the Listview's editing textbox exists then we
  ' need to get its text and update the Listview and then destroy it.
  sText = FF_TextBox_GetText( gListviewEdit.hTextBox )
  FF_ListView_SetItemText HWND_FORM1_LISTVIEW1, gListviewEdit.nRow, gListviewEdit.nCol, sText
   
  ShowWindow gListviewEdit.hTextBox, %SW_HIDE
   
End Function



'------------------------------------------------------------------------------------------------------------------------
Function FORM1_TXTLISTVIEWEDIT_WM_KEYUP ( _
                                       ControlIndex  As Long,  _  ' index in Control Array
                                       hWndForm      As Dword, _  ' handle of Form
                                       hWndControl   As Dword, _  ' handle in Control
                                       nVirtKey      As Long,  _  ' virtual key code
                                       lKeyData      As Long   _  ' key data
                                       ) As Long

  Select Case nVirtKey
     
     Case %VK_RETURN, %VK_ESCAPE
        CancelListviewEdit
     
  End Select

End Function
Title: Find Cell location and size
Post by: Haakon Birkeland on August 17, 2006, 09:24:13 PM
Thanx the code does work I adjusted the width and height a little bit because it hid the grid line.
The only problem I have is that if I move the mouse pointer some where else on the grid the textbox loses its focus.
example:
I hilite cell row 10 col 2
If I move the mouse pointer toward row 9 to 0 the text box stays in focus
If I move toward row 11 the text box loses focus and the listview background shows.
Any idea

thanx
bert
Title: Find Cell location and size
Post by: TechSupport on August 17, 2006, 10:56:51 PM
You must have other code somewhere in there that is responding to a WM_MOUSEMOVE message or similar ???? The example code that I posted does not exhibit the behaviour that you are describing. I can move the mouse anywhere over the Listview and the TextBox always keeps focus. It loses focus if a different cell in the Listview is clicked.
Title: Find Cell location and size
Post by: Haakon Birkeland on August 18, 2006, 10:29:41 AM
I couldn't find code. But I deleted the lisview and the associated code. Then reinstall and it worked must have been a check ark somewhere. Now everything works. Again thanx for the help.

Bert
Title: Find Cell location and size
Post by: Haakon Birkeland on August 22, 2006, 12:39:08 AM
One question.
I noticed you put the code in KeyUp
Is there a reason to use it there instead of KeyDown?

Just curious

Bert
Title: Find Cell location and size
Post by: Roger Garstang on August 22, 2006, 04:59:05 AM
Last event fired for the key...less likely to misfire another event when Up event is triggered after it.  Also in some cases maybe the user wants to cancel much like a button press-  If you go to click a button then at that last split second decide not to you can move off the button and then release...then since no MouseUp on the button it is canceled.