 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
wtg Guest
|
Posted: Tue Oct 03, 2006 9:41 pm Post subject: Can you move a listview column programmatically? |
|
|
I have a need for a checkbox on a listview column other than the first. I've found I can create a listview with the checkbox and then move the column to a different position via my mouse, dragging Col 1 to the 4th column position, for instance. However, I can't find a way to accomplish the same thing programmatically.
Is the only way to accomplish this going to be feeding the GUI an emulated mouse click and drag, or am I missing something obvious?
Sorry if this is covered somewhere. I've read the help file extensively and searched the forums with no luck. |
|
| Back to top |
|
 |
PhiLho
Joined: 27 Dec 2005 Posts: 6721 Location: France (near Paris)
|
|
| Back to top |
|
 |
wtg
Joined: 04 Oct 2006 Posts: 63 Location: Louisville, KY
|
Posted: Wed Oct 04, 2006 6:47 pm Post subject: LVM_SETCOLUMNORDERARRAY |
|
|
Thanks for pointing that out to me PhiLho. It's a bit more than I was ready for, but I think I'm getting close.
Can you see what's wrong with my test program below? I've never used SendMessage before (and have only used AHK for about a week) and so I've had to scrounge the help file and the forums to figure out what to do. I'm sure I'm probably making a newbie mistake, but I can't see why this won't reorder column 1 and 2.
| Code: |
Gui, Add, ListView, grid Checked vTestList, Column 1|Column 2|Column 3
Gui, Add, Button, gSwap, Swap
Gui, Add, Statusbar
Gui, Show, Autosize Center +Resize,Swap Test
lv_Add("", "r1c1", "r1c2", "r1c3")
lv_Add("", "r2c1", "r2c2", "r2c3")
lv_Add("", "r3c1", "r3c2", "r3c3")
Return
Swap:
cap = 3*4
VarSetCapacity(ColOrder, cap, 0)
InsertInteger(1, ColOrder, 0*4)
InsertInteger(0, ColOrder, 1*4)
InsertInteger(2, ColOrder, 2*4)
SendMessage, 0x103A, cap, &ColOrder, TestList, ahk_class AutoHotkeyGUI
MsgBox Errorlevel = %ErrorLevel%
return
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)
}
GuiClose:
ExitApp
|
|
|
| Back to top |
|
 |
PhiLho
Joined: 27 Dec 2005 Posts: 6721 Location: France (near Paris)
|
Posted: Thu Oct 05, 2006 11:04 am Post subject: |
|
|
Some errors: wParam is the number of elements in the array, not the size of the buffer in bytes; cap = 3*4 is a classical error, it should be cap := 3*4; AFAIK, SendMessage doesn't take a GUI control variable name (it is not a GUI command), you have to put the ClassNN.
I have made a function out of your code:
| Code: | Gui Add, ListView, grid Checked vTestList, C1|C2|C3|C4|C5
Gui Add, Button, gSwap, Swap
Gui Add, Statusbar
Gui Show, Autosize Center +Resize, Swap Test
LV_Add("", "r1c1", "r1c2", "r1c3", "r1c4", "r1c5")
LV_Add("", "r2c1", "r2c2", "r2c3", "r2c4", "r2c5")
LV_Add("", "r3c1", "r3c2", "r3c3", "r3c4", "r3c5")
LV_ModifyCol()
Return
Swap:
colNb := LV_GetCount("Column")
Random col1, 1, colNb
Loop
{
Random col2, 1, colNb
If (col2 != col1)
Break
}
Swap(col1, col2, colNb, 1)
LV_ModifyCol()
return
; Swap two columns of the list view # _lvID, given by their index, starting at 1
Swap(_col1, _col2, _colNb, _lvID)
{
local colOrder, pos
VarSetCapacity(colOrder, _colNb * 4, 0)
Loop %_colNb%
{
pos := A_Index - 1
If (A_Index = _col1)
InsertInteger(_col2 - 1, colOrder, pos * 4)
Else If (A_Index = _col2)
InsertInteger(_col1 - 1, colOrder, pos * 4)
Else
InsertInteger(pos, colOrder, pos * 4)
}
SendMessage 0x1000 + 58 ; LVM_SETCOLUMNORDERARRAY
, _colNb, &colOrder, SysListView32%_lvId%, A
SendMessage 0x1000 + 21 ; LVM_REDRAWITEMS
, 0, _colNb - 1, SysListView32%_lvId%, A
}
| [EDIT: The ListView needs a redraw message to correctly update. Also added more columns and random swapping for test...] _________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2") |
|
| Back to top |
|
 |
wtg
Joined: 04 Oct 2006 Posts: 63 Location: Louisville, KY
|
Posted: Thu Oct 05, 2006 1:08 pm Post subject: |
|
|
PhiLho,
Thank you so much... you really helped clarify things.
I didn't understand how to provide the handle to the list control. If I understand correctly, it's SysListView321 because this was the first list added to the screen, and the second added would be SysListView322 and so on. Is there a function of any kind, or can one be written, that would return SysListView32n using just the list variable name? I mean, AHK commands that manipulate the list using it's variable name are essentially converting those references to the appropriate SysListView32n reference behind the scenes, right?
The cap assignment problem was something I introduced after the fact cleaning up code to post, and using it as the # of elements in the SendMessage command is a bug I introduced while trying to figure out why my call wasn't working. It's one of those changes that could have taken me another day to figure out once I got the list controls handle right, or may not have gotten them both right at the same time without your help.
By the way, you used the LVM_REDRAWITEMS command to make the columns redraw. Is there an advantage to doing this over a simple GuiControl, +Redraw, TestList?
Thanks again! |
|
| Back to top |
|
 |
PhiLho
Joined: 27 Dec 2005 Posts: 6721 Location: France (near Paris)
|
Posted: Thu Oct 05, 2006 1:37 pm Post subject: |
|
|
| wtg wrote: | | By the way, you used the LVM_REDRAWITEMS command to make the columns redraw. Is there an advantage to doing this over a simple GuiControl, +Redraw, TestList? | Probably no... I just had the nose in MSDN, so I searched there instead of AHK doc. I wouldn't have thought of it anyway, as the doc. presents it as a pair with -Redraw (block updates, then re-allow them).
Mapping a GUI control ClassNN to its variable name is a bit tricky.
One way (the only one?) is to use:
GuiControlGet var, FocusV
so you have to do a GuiControl Focus first (can be done once just after the Gui building). _________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2") |
|
| Back to top |
|
 |
wtg
Joined: 04 Oct 2006 Posts: 63 Location: Louisville, KY
|
Posted: Thu Oct 05, 2006 2:09 pm Post subject: |
|
|
| PhiLho wrote: | [Mapping a GUI control ClassNN to its variable name is a bit tricky.
One way (the only one?) is to use:
GuiControlGet var, FocusV
so you have to do a GuiControl Focus first (can be done once just after the Gui building). |
Doing some more reading after your suggestion I believe you meant GuiControlGet,var,Focus instead of FocusV. That's really helpful. Since the ListView variable isn't actually used to store a value by the control, one could as a matter of practice use:
| Code: |
GuiControl,Focus,MyList
GuiControlGet,MyList,Focus |
right after building the screen, storing the ClassNN value in the control's variable. Seems as good a thing as anything to store in the variable. |
|
| Back to top |
|
 |
PhiLho
Joined: 27 Dec 2005 Posts: 6721 Location: France (near Paris)
|
Posted: Thu Oct 05, 2006 4:19 pm Post subject: |
|
|
Yes, I got it the way around... (I shown how to get a variable name, not the ClassNN.) Sorry. but at least it pushed you in the right direction.  _________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2") |
|
| Back to top |
|
 |
adamrgolf
Joined: 28 Dec 2006 Posts: 362
|
Posted: Wed Jun 27, 2007 10:15 am Post subject: |
|
|
| PhiLho wrote: | Some errors: wParam is the number of elements in the array, not the size of the buffer in bytes; cap = 3*4 is a classical error, it should be cap := 3*4; AFAIK, SendMessage doesn't take a GUI control variable name (it is not a GUI command), you have to put the ClassNN.
I have made a function out of your code:
| Code: | Gui Add, ListView, grid Checked vTestList, C1|C2|C3|C4|C5
Gui Add, Button, gSwap, Swap
Gui Add, Statusbar
Gui Show, Autosize Center +Resize, Swap Test
LV_Add("", "r1c1", "r1c2", "r1c3", "r1c4", "r1c5")
LV_Add("", "r2c1", "r2c2", "r2c3", "r2c4", "r2c5")
LV_Add("", "r3c1", "r3c2", "r3c3", "r3c4", "r3c5")
LV_ModifyCol()
Return
Swap:
colNb := LV_GetCount("Column")
Random col1, 1, colNb
Loop
{
Random col2, 1, colNb
If (col2 != col1)
Break
}
Swap(col1, col2, colNb, 1)
LV_ModifyCol()
return
; Swap two columns of the list view # _lvID, given by their index, starting at 1
Swap(_col1, _col2, _colNb, _lvID)
{
local colOrder, pos
VarSetCapacity(colOrder, _colNb * 4, 0)
Loop %_colNb%
{
pos := A_Index - 1
If (A_Index = _col1)
InsertInteger(_col2 - 1, colOrder, pos * 4)
Else If (A_Index = _col2)
InsertInteger(_col1 - 1, colOrder, pos * 4)
Else
InsertInteger(pos, colOrder, pos * 4)
}
SendMessage 0x1000 + 58 ; LVM_SETCOLUMNORDERARRAY
, _colNb, &colOrder, SysListView32%_lvId%, A
SendMessage 0x1000 + 21 ; LVM_REDRAWITEMS
, 0, _colNb - 1, SysListView32%_lvId%, A
}
| [EDIT: The ListView needs a redraw message to correctly update. Also added more columns and random swapping for test...] |
I have a need for this as well, however i cannot get PhiLho's code, quoted here, to work so I can see a demonstration.
Am I doing something wrong? |
|
| Back to top |
|
 |
adamrgolf
Joined: 28 Dec 2006 Posts: 362
|
Posted: Wed Jun 27, 2007 10:22 am Post subject: |
|
|
My bad -- the code needed to be as follows to test (duh):
| Code: | Gui Add, ListView, grid Checked vTestList, C1|C2|C3|C4|C5
Gui Add, Button, gSwap, Swap
Gui Add, Statusbar
Gui Show, Autosize Center +Resize, Swap Test
LV_Add("", "r1c1", "r1c2", "r1c3", "r1c4", "r1c5")
LV_Add("", "r2c1", "r2c2", "r2c3", "r2c4", "r2c5")
LV_Add("", "r3c1", "r3c2", "r3c3", "r3c4", "r3c5")
LV_ModifyCol()
Return
Swap:
colNb := LV_GetCount("Column")
Random col1, 1, colNb
Loop
{
Random col2, 1, colNb
If (col2 != col1)
Break
}
Swap(col1, col2, colNb, 1)
LV_ModifyCol()
return
; Swap two columns of the list view # _lvID, given by their index, starting at 1
Swap(_col1, _col2, _colNb, _lvID)
{
local colOrder, pos
VarSetCapacity(colOrder, _colNb * 4, 0)
Loop %_colNb%
{
pos := A_Index - 1
If (A_Index = _col1)
InsertInteger(_col2 - 1, colOrder, pos * 4)
Else If (A_Index = _col2)
InsertInteger(_col1 - 1, colOrder, pos * 4)
Else
InsertInteger(pos, colOrder, pos * 4)
}
SendMessage 0x1000 + 58 ; LVM_SETCOLUMNORDERARRAY
, _colNb, &colOrder, SysListView32%_lvId%, A
SendMessage 0x1000 + 21 ; LVM_REDRAWITEMS
, 0, _colNb - 1, SysListView32%_lvId%, A
}
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)
}
GuiClose:
ExitApp |
|
|
| Back to top |
|
 |
wtg
Joined: 04 Oct 2006 Posts: 63 Location: Louisville, KY
|
Posted: Wed Jun 27, 2007 1:54 pm Post subject: |
|
|
| Glad you got it sorted out. |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|