AutoHotkey Community

It is currently May 25th, 2012, 9:45 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 14 posts ] 
Author Message
 Post subject: Listview In-Cell Editing
PostPosted: June 9th, 2007, 7:17 am 
Offline

Joined: December 1st, 2006, 9:27 am
Posts: 460
This features in-cell editing and cell highlighting. The cell highlighting needs some work, but the editing works great.
Just double-click on a cell to edit and press enter when done. To cancel, hit ESC or click on another cell. When the cell is double-clicked, if it is scrolled too far left to be fully visible, the listview will scroll to show the cell contents fully. Cell highlighting works the same way.
This works with or without the checkboxes and (I assume) icons. The listview may also be scrolled either horizontally or vertically.
I needed this for a project so I thought I'd share it!
Code:
LV = SysListView321   ;set the controls to use
ED = Edit1
ST = Static1
FontSize = 10

EnableSingleClick = 1   ;whether or not to do cell highlighting on singleclick

SysGet,SM_CXVSCROLL,2         ;get width of vertical scrollbar
LVIR_LABEL = 0x0002            ;LVM_GETSUBITEMRECT constant - get label info
LVM_GETITEMCOUNT = 4100      ;gets total number of rows
LVM_SCROLL = 4116               ;scrolls the listview
LVM_GETTOPINDEX = 4135      ;gets the first displayed row
LVM_GETCOUNTPERPAGE = 4136   ;gets number of displayed rows
LVM_GETSUBITEMRECT = 4152   ;gets cell width,height,x,y

LVS_SINGLESEL = 0x4                     ;allow one item to be selected
LVS_SHOWSELALWAYS = 0x8               ;shows selection highlighting even if no focus
LVS_EX_FULLROWSELECT = LV0x20         ;whole row selection

listOptions =
   (Join`s LTrim
      +AltSubmit
      -Checked
      +Grid
      -%LVS_EX_FULLROWSELECT%
      -%LVS_SHOWSELALWAYS%
      +%LVS_SINGLESEL%
   )

AutoTrim,Off   
DetectHiddenWindows,On
Gui,+LastFound
guiID := WinExist()   ;get id for gui
GroupAdd,editKeypress,ahk_id %guiID%   ;for ENTER and ESC handling
Gui, Font, s%FontSize%, Arial   ;set font for listview1,static1 and edit1
Gui, Add, ListView, r20 w525 %listOptions% vlview glistClick, Name|Modified|FullPath   ;make listview
Gui, Add, Edit, x0 y-50 vCellEdit   ;make edit control
Gui, Add, Text, x0 y-50 vCellHighlight +Border cBlue -Wrap   ;make static1 control
ControlGetPos,lx,ly,lw,lh,%LV%,ahk_id %guiID%   ;get info on listview

;********just to fill the listview********
; Gather a list of file names from a folder and put them into the ListView:
Loop, %A_MyDocuments%\*.*
{   If A_Index>40
      Break
   LV_Add("", A_LoopFileName, A_LoopFileTimeModified, A_LoopFileLongPath)
}
LV_ModifyCol()   ;autosize columns

Gui, Show
Return

;TODO:
;singleclick in listview not reliable - find another way other than "Normal" maybe "C" with other condition
;can't highlight text in edit1 with mouse, just calls listClick
;maybe use arrow keys with a static control cell overlay to emulate cell highlighting? - partially done

listClick:
   CoordMode,MOUSE,RELATIVE
   MouseGetPos,mx,my,oID,oCNN
   If(A_GuiEvent = "DoubleClick")
   {   Gosub doubleclick
   }
   Else If(A_GuiEvent = "Normal" and EnableSingleClick)
   {   Gosub singleclick
   }
   Else If A_GuiEvent In S,s,RightClick,ColClick,D,d,e      ;hide edit on these events
   {   GuiControl,Hide,%ST%   ;hide static control
      GuiControl,Hide,%ED%   ;hide edit control
   }
Return

doubleclick:
   GuiControl,Hide,%ED%   ;hide edit control
   GuiControl,Hide,%ST%   ;hide static control
   DispControl := ED      ;make edit1 the default control
   spacer =
   Gosub CellInfo
   Gosub CellReSize
   Gosub CellPosition
   GuiControl,Focus,%DispControl%   ;set focus   
   SetTimer,isEditFocused,75   ;start edit focus monitor
Return

singleclick:
   GuiControl,Hide,%ED%   ;hide edit control
   GuiControl,Hide,%ST%   ;hide edit control
   DispControl := ST   ;make static1 the default control
   spacer = %A_Space%
   Gosub CellInfo
   Gosub CellReSize
   Gosub CellPosition
   GuiControl,Focus,%LV%   ;set focus   
Return

;*************************cell size and position stuff******************************
CellInfo:
   SendMessage,LVM_GETITEMCOUNT,0,0,%LV%,ahk_id %guiID%
   TotalNumOfRows := ErrorLevel   ;get total number of rows
   SendMessage,LVM_GETCOUNTPERPAGE,0,0,%LV%,ahk_id %guiID%
   NumOfRows := ErrorLevel   ;get number of displayed rows
   SendMessage,LVM_GETTOPINDEX,0,0,%LV%,ahk_id %guiID%
   topIndex := ErrorLevel   ;get first displayed row
   
   VarSetCapacity(XYstruct, 16, 0)   ;create struct
   Loop,%NumOfRows%   ;gets the current row, and cell Y,H
   {   which := topIndex + A_Index -1   ;loop through each displayed row
      InsertInteger(LVIR_LABEL   ,XYstruct,0)   ;get label info constant
      InsertInteger(A_Index-1   ,XYstruct,4)   ;subitem index
      SendMessage,LVM_GETSUBITEMRECT,%which%,&XYstruct,%LV%,ahk_id %guiID%   ;get cell coords
      RowY     := ExtractInteger(XYstruct,4,4) + ly   ;row upperleft y = itempos y + listview y
      RowY2    := ExtractInteger(XYstruct,12,4) + ly   ;row bottomright y2 = itempos y2 + listview y
      currColHeight := RowY2 - RowY ;get cell height
      If(my <= RowY + currColHeight)   ;if mouse Y pos less than row pos + height
      {   currRow    := which   +1   ;1-based current row
         currRow0   := which      ;0-based current row
         Break
      }
   }
   
   VarSetCapacity(XYstruct, 16, 0)   ;create struct
   Loop % LV_GetCount("Col")   ;gets the current column, and cell X,W
   {   InsertInteger(LVIR_LABEL   ,XYstruct,0)   ;get label info constant
      InsertInteger(A_Index-1   ,XYstruct,4)   ;subitem index
      SendMessage,LVM_GETSUBITEMRECT,%currRow0%,&XYstruct,%LV%,ahk_id %guiID%   ;get cell coords
      RowX    := ExtractInteger(XYstruct,0,4) + lx   ;row upperleft x = itempos x + listview x
      RowX2    := ExtractInteger(XYstruct,8,4) + lx   ;row bottomright x2 = itempos x2 + listview x
      currColWidth := RowX2 - RowX   ;get cell width
      If(mx <= RowX + currColWidth)   ;if mouse X pos less than column pos+width
      {   currCol := A_Index   ;get current column number
         Break
      }
   }
Return

CellReSize:
   If(RowX < lx)   ;make sure the cell is in view, then get the cell x coord again if it wasn't
   {   hscrollVal := RowX - lx - 4    ;get the difference
      SendMessage,LVM_SCROLL,%hscrollVal%,0,%LV%,ahk_id %guiID%   ;scroll the column into view
      VarSetCapacity(XYstruct, 16, 0)   ;recreate struct
      InsertInteger(LVIR_LABEL   ,XYstruct,0)   ;get just label coords
      InsertInteger(currCol-1      ,XYstruct,4)   ;1-based subitem index
      SendMessage,LVM_GETSUBITEMRECT,%currRow0%,&XYstruct,%LV%,ahk_id %guiID%   ;get cell coords
      RowX    := ExtractInteger(XYstruct,0,4) + lx   ;row upperleft x = itempos x + listview x
   }
   
   scrollWidth := TotalNumOfRows > NumOfRows ? SM_CXVSCROLL : 0   ;0 if no vscroll, else = SM_CXVSCROLL
   If(RowX+currColWidth > lx+lw-scrollWidth)   ;if edit will be too wide, shrink it
   {   currColWidth -= ((RowX+currColWidth) - (lx+lw-scrollWidth)) + 3
   }
Return

CellPosition:
   CellX_LV := currCol                           ;get cell column
   CellY_LV := currRow                           ;get cell row
   LV_GetText(coltxt,CellY_LV,CellX_LV)         ;get the text
   edW := currColWidth                        ;get control width
   edH := currColHeight + 1                     ;get control height
   edX := RowX + 2                              ;get control x pos
   edY := RowY + 1                              ;get control y pos
   ControlMove,%DispControl%,edX,edY,edW,edH   ;move and size control
   GuiControl,,%DispControl%,%spacer%%colTxt%            ;set the text
   GuiControl,Show,%DispControl%                  ;show control
Return

CellHide:
   GuiControl,Hide,%DispControl%
   ;GuiControl,Focus,%ED%   ;set focus   
Return
;*************************end cell size and position stuff******************************

isEditFocused:
   GuiControlGet,cFoc,Focus
   If(cFoc != DispControl)
   {   SetTimer,isEditFocused,Off
      Gosub CellHide
   }
Return

guiClose:
   ExitApp
Return

#IfWinActive ahk_group editKeypress
Enter::
   GuiControlGet,fControl,Focus   ;get control with focus
   If(fControl = DispControl)   ;if Edit, save any changes
   {   Gui,Submit,NoHide
      CellX_save = Col%CellX_LV%
      LV_Modify(CellY_LV,CellX_save,CellEdit)
      Gosub CellHide
   }
Return

Esc::
   Gosub CellHide   ;cancel
Return

Up::   ;if arrow keys pressed while cell highlighted
Down::
Left::
Right::
   If(DispControl = ST)   ;TODO
   {   If(A_ThisHotkey = "Left")
      {   
      }
      Else If(A_ThisHotkey = "Right")
      {   
      }
      Else If(A_ThisHotkey = "Up")
      {   
      }
      Else If(A_ThisHotkey = "Down")
      {   
      }
   }
Return
#IfWinActive






InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; The caller must ensure that pDest has sufficient capacity.  To preserve any existing contents in pDest,
; only pSize number of bytes starting at pOffset are altered in it.
{
    Loop %pSize%  ; Copy each byte in the integer into the structure as raw binary data.
        DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
}

ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4)
; pSource is a string (buffer) whose memory area contains a raw/binary integer at pOffset.
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned.
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int).
; pSource must be ByRef to avoid corruption during the formal-to-actual copying process
; (since pSource might contain valid data beyond its first binary zero).
{
    Loop %pSize%  ; Build the integer by adding up its bytes.
        result += *(&pSource + pOffset + A_Index-1) << 8*(A_Index-1)
    if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
        return result  ; Signed vs. unsigned doesn't matter in these cases.
    ; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
    return -(0xFFFFFFFF - result + 1)
}

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 9th, 2007, 12:39 pm 
Offline

Joined: May 24th, 2006, 2:49 pm
Posts: 4511
Location: Belgrade
Thats why I said to Laszlo once that it is possible to create grid out of ListView.

Good job.

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 9th, 2007, 7:53 pm 
Offline

Joined: December 1st, 2006, 9:27 am
Posts: 460
Thanks!
It seems to be something that is asked for often, so hopefully it will get some use.

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 26th, 2007, 9:16 am 
Offline

Joined: November 20th, 2007, 8:36 am
Posts: 7
Location: usa
Micahs: This is fantastic!! I have been wanting to have this capability in my project, and finally started searching for it. I was able to pick out the relevant parts and merge into my code, run, and it works the first time. I am really impressed and grateful for your sharing. Have you done any further work on it?

I am able also to edit a cell, and retrieve the edited value correctly.

Thanks.

Bob :D


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 26th, 2007, 10:54 am 
Offline

Joined: December 1st, 2006, 9:27 am
Posts: 460
Yeah, I have. I can't remember where I left off but I'll pull it out, check it over, and get back with you.

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 26th, 2007, 1:58 pm 
Offline

Joined: November 20th, 2007, 8:36 am
Posts: 7
Location: usa
Micah, I think you have left someone with a fun puzzle. :D

I can get the edit control to move, but it keeps jumping back to the original double-clicked cell. I will study it more later.

Thanks,

Bob


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 26th, 2007, 10:33 pm 
Offline

Joined: April 17th, 2007, 1:37 pm
Posts: 761
Location: Florida
Very cool script... I wonder if it can be applied to a CSV-editor type application.

_________________
[Join IRC!]
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 29th, 2007, 2:49 am 
Offline

Joined: December 1st, 2006, 9:27 am
Posts: 460
TerrapinII wrote:
it keeps jumping back to the original double-clicked cell
I had solved that but never reposted. I started working on this again after your post and made many improvements. I'll post it soon (there are some nagging problems to fix first!)

Rhys wrote:
I wonder if it can be applied to a CSV-editor type application
I think it could. I had in mind an ini editor type thing, but haven't pursued it yet. That project has been on the back burner for a while.
Some of the features I added were with a spreadsheet-type editor in view.

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 21st, 2008, 1:07 pm 
Offline

Joined: October 20th, 2005, 11:56 am
Posts: 23
Hi Micahs
This script is very close to what I need but I require navigating the listview with the arrow keys.
I can see the 'ToDo' in the script and was wondering if you had a chance to complete this.
I would try myself but most of this is way above my head.

Thanks anyways.
Brett

_________________
Everyone makes mistakes, that's why they put erasers on pencils. Milhouse, The Simpsons


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 9th, 2008, 2:21 am 
Offline

Joined: December 1st, 2006, 9:27 am
Posts: 460
@TerrapinII
Holy crap! I totally forgot to upload again. I can't believe that it's been almost a year! That tells you how bad my memory is. "I'll post it soon" HAH!

@doublebogey
I wasn't ignoring you. Thanks for the reminder.

Hear it goes: Listview In-cell Editing Latest

This has not been updated recently, and I have not cleaned up the code much.

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 24th, 2010, 1:47 pm 
Offline

Joined: July 31st, 2008, 10:27 pm
Posts: 336
Hi Micah.

I can not seem to get this to work with any gui, other than gui1.
Even if I change the sample code for Project Manager to:

Code:
#include listviewCellEdit.ahk      ;include in-cell editing   module -   for in-cell editing
Gui, 5:Default
Gui,+Resize
Gui, Font, s%LV_FontSize%, Arial   ;set font for listview, static and edit (and everything else, of course)
Gui,Add,Listview,x5 y5 w600 r25 vlview  hwndLV_LView   ;create the listview - must specify vlview variable name and hwnd (LV_LView)
;GuiAddListview("lview", "x5 y5 w600 r25","s10 Arial",1)   ;maybe switch to something like this? first param is control variable, second param is size and pos, third is font stuff, fourth param is guinumber and is optional - default = 1
Gui,Add,Button,,Update
Gui, Show, x113 y124, ProductManager
InitCellEditing("lview", 5)   ;enable in-cell editing   -   for in-cell editing, must be after all controls other are added
Return


The project manager does not work correctly.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 24th, 2010, 11:17 pm 
Offline

Joined: December 1st, 2006, 9:27 am
Posts: 460
Hi Morpheus!

Unfortunately, I found this at the top of the latest version: "TODO: Finish making changes to allow celledit listviews on multiple guis."

I have not made this project a priority lately. I kind of need it for another project, though. I will look into this. Thanks for the reminder!

In the meantime, try putting this in the "InitCellEditing" sub:

Code:
   Gui,%LV_g%:+LastFound    ;After this...
   Gui,%LV_g%:+Default    ;add this.


That makes it take effect inside the sub. Didn't test if it will work, though. HTH

micahs

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 25th, 2010, 1:46 pm 
Offline

Joined: July 31st, 2008, 10:27 pm
Posts: 336
Thanks for the reply. Your suggestion did not work, although I'm sure I can work around it by switching my various Gui #'s.

I just wanted to let you know the result of your suggestion.

Have a Merry Christmas!


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 25th, 2010, 7:07 pm 
Offline

Joined: December 1st, 2006, 9:27 am
Posts: 460
Thanks for the update! It was a bit of a simplistic solution and doesn't take into consideration the nested funcs. Oh well...

I will fix this (meant to but never got around to it.)

Have a great one!

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 14 posts ] 

All times are UTC [ DST ]


Who is online

Users browsing this forum: Bing [Bot], Exabot [Bot] and 5 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group