AutoHotkey Community

It is currently May 27th, 2012, 10:17 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 118 posts ]  Go to page Previous  1 ... 4, 5, 6, 7, 8  Next
Author Message
 Post subject:
PostPosted: June 21st, 2010, 7:59 pm 
Offline

Joined: October 4th, 2006, 2:15 am
Posts: 250
Location: Louisville, KY
Yeah, that's what I'm looking in to. I'm sure I don't know enough to do it, but perhaps I will before I give up. :)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 22nd, 2010, 7:39 am 
Offline

Joined: May 24th, 2006, 2:49 pm
Posts: 4511
Location: Belgrade
Actually, its quite easy.
You need to trap EB notification event from SS and use ComboX_Show on specific cell coordinates. As a note, it might work better if you launch ComboX in its own thread (that is, return from OnNotify of SS as soon as possible and do lengthy jobs elsewhere; it can be done using SetTimer). I already presented something similar with SysListView control and ComboX.

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 22nd, 2010, 8:07 pm 
Offline

Joined: October 4th, 2006, 2:15 am
Posts: 250
Location: Louisville, KY
I'm not done yet but at least getting it working fairly simply, using the button control to launch ComboX. On problem though, I can't get it to use the Webding font and I was hoping to create a "text" down arrow button like you have in the ComboX _test script.

I can change the font the program uses to other fonts, but it seems to ignore the Webding and Wingding fonts entirely. Do you see any reason for that?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 22nd, 2010, 8:13 pm 
Offline

Joined: May 24th, 2006, 2:49 pm
Posts: 4511
Location: Belgrade
Just use picture control or some other charachter like ">".
There are also ways to use image with button, see ILButton @ Forms framework.

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 22nd, 2010, 8:18 pm 
Offline

Joined: October 4th, 2006, 2:15 am
Posts: 250
Location: Louisville, KY
Yeah, I figured I could use an image control but the text button with the Webding font is, err... should be, easier.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 22nd, 2010, 10:34 pm 
Offline

Joined: May 24th, 2006, 2:49 pm
Posts: 4511
Location: Belgrade
U can also try with Forms\Font module.

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject: Bug in SS_GetCellText
PostPosted: July 6th, 2010, 4:50 pm 
Offline

Joined: October 4th, 2006, 2:15 am
Posts: 250
Location: Louisville, KY
I found an issue with SS_GetCellText: it doesn't support fetching the column header text. I've provided a fix below.

Code:
SS_GetCellText(hCtrl, Col="", Row=""){
   ;fast version for GetCell but only for text
   static EMPTY=0, COLHDR=1, ROWHDR=2, WINHDR=3, TEXT=4, TEXTMULTILINE=5, INTEGER=6, FLOAT=7, FORMULA=8, GRAPH=9, HYPERLINK=10, CHECKBOX=11, COMBOBOX=12, OWNERDRAWBLOB=13, OWNERDRAWINTEGER=14, EXPANDED=15, BUTTON=16, WIDEBUTTON=0x20, DATE=0x30, FORCETEXT=0x44, FORCETYPE=0x40, FIXEDSIZE=0x80
   static SPRM_GETCELLDATA=0x482, SPRIF_DATA=0x200, SPRIF_TYPE=0x40
   static ITEM, init

   if !init
      init++, VarSetCapacity(ITEM, 40, 0), NumPut(SPRIF_DATA | SPRIF_TYPE, ITEM)

   if Col=
      SS_GetCurrentCell(hCtrl, Col, Row)

   NumPut(Col,   ITEM, 4), NumPut(Row, ITEM, 8)
   SendMessage,SPRM_GETCELLDATA,,&ITEM,, ahk_id %hCtrl%

   type := NumGet(ITEM, 27, "UChar") & ~0xF0   ;get base type

   if type=%COLHDR%
      return SS_strAtAdr( NumGet(ITEM, 36)+2 )


   if type in %TEXT%,%TEXTMULTILINE%,%HYPERLINK%,%CHECKBOX%,%OWNERDRAWBLOB%      ;GRAPH and FORMULA don't return text, I don't know how to get their text.
      return SS_strAtAdr( NumGet(ITEM, 36) + (type=CHECKBOX || type=OWNERDRAWBLOB ? 4 : 0))

   if type in %INTEGER%,%COMBOBOX%,%OWNERDRAWINTEGER%
   {
      pData := NumGet(ITEM, 36), txt := NumGet( pData+0 )
      if (type=COMBOBOX)      ;combobox, get the item from the listbox
      {
         hCombo := NumGet(pData + 4)
         old := A_DetectHiddenWindows
         DetectHiddenWindows, on
         ControlGet, lst, list,,, ahk_id %hCombo%
         DetectHiddenWindows, %old%
         loop, parse, lst, `n
            if (A_index = txt+1) {
               txt := A_LoopField
               break
            }
      }
      return txt
   }

   if type in %FLOAT%,%FORMULA%
       return SS_getCellFloat(hCtrl, col, row)
}


Btw, the function doesn't support cell type ROWHDR or WINHDR either. I haven't investigated those types so I'm not sure what the solution would be, or if fetching the cell text is even appropriate for them.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 6th, 2010, 5:00 pm 
Offline

Joined: May 24th, 2006, 2:49 pm
Posts: 4511
Location: Belgrade
Thx for the fix. I committed your changes to repository.
About other issues, I don't know more then you about it.

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 6th, 2010, 5:11 pm 
Offline

Joined: May 24th, 2006, 2:49 pm
Posts: 4511
Location: Belgrade
BTW, about cell unhide and unlock you can definitely do this.

You will need to avoid wrapper for that tho. U need to get numeric cell state and clear "hidden" mark.

You will use GetCell with SPRIF_STATE flag to get numeric flag. The SS_GetCell does that but converts numeric into text description in lines:

Code:
      if field in type,state,align
         fun := "SS_get" field, v := %fun%( v )      



SS_getState does the conversion job from numeric to text and vice versa. You have declarations there for states, for instance HIDDEN=0x02.

Now, to unhide the cell you need to get cell state, clear its "hidden" flag and set the new numeric state again. You could incorporate those changes into current API with some special symbols like -|+|* becaue I will probably be to lazy to do it until I need it myself.

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 6th, 2010, 6:11 pm 
Offline

Joined: October 4th, 2006, 2:15 am
Posts: 250
Location: Louisville, KY
majkinetor wrote:
SS_getState does the conversion job from numeric to text and vice versa. You have declarations there for states, for instance HIDDEN=0x02.

Now, to unhide the cell you need to get cell state, clear its "hidden" flag and set the new numeric state again. You could incorporate those changes into current API with some special symbols like -|+|* becaue I will probably be to lazy to do it until I need it myself.


Thanks majkinetor. I've considered making a SS_SetState to do this but like you, don't really need it - setting the state to 0 works for my application - and thus haven't gotten around to it yet.

Your mentioning it did remind me that I have created another routine that others might find useful: SS_GetGlobalFields(). I found I needed it to fetch the column and row header height and widths, and it's a one-call method to fetch both the row and column counts simultaneously.

Code:
/*
   Function: GetGlobalFields
           Get individual global parameters from the control.

   Parameters:
           fields -   White space separated list of field names to get.
           v1 .. v7 - Field values, respecting the order of names in fields argument.

   Example:
>         SS_GetGlobalFields(hCtrl, "nrows ncols", rows, cols)
 */
SS_GetGlobalFields(hCtrl, Fields, ByRef v1="", ByRef v2="", ByRef v3="", ByRef v4="", ByRef v5="", ByRef v6="", ByRef v7="") {
   static SPRM_SETGLOBAL=0x489, SPRM_GETGLOBAL=0x488      ; wParam=0, lParam=cols
   static colhdrbtn=0,rowhdrbtn=4,winhdrbtn=8,lockcol=12,hdrgrdcol=16
         ,grdcol=20,bcknfcol=24,txtnfcol=28,bckfocol=32,txtfocol=36
         ,ncols=40,nrows=44,ghdrwt=48,ghdrht=52,gcellw=56,gcellht=60
   static _bg=0, _fg=4, _txtal=8.1, _imgal=9.1, _fnt=10.1, _tpe=11.1
   static colhdr=64, rowhdr=76, winhdr=88, cell=100
   static LEFT=0x10, CENTER=0x20, RIGHT=0x30, MIDDLE=0x40
        , BOTTOM=0x80, GLOBAL=0xF0, MASK=0xF0, XMASK=0x30, YMASK=0xC0
   static alignments := "LEFT CENTER RIGHT MIDDLE BOTTOM"

   VarSetCapacity(GLOBAL, 112, 0)
   SendMessage,SPRM_GETGLOBAL,0,&GLOBAL,, ahk_id %hCtrl%

   loop, parse, Fields, %A_Space%%A_Tab%
   {
      field := A_LoopField
      if (j := InStr(field, "_"))
           offset := SubStr(field, 1, j-1),  offset := %offset%, _ := SubStr(field, j), _ := %_%,  offset += floor(_), t := SubStr(_, -1)
      else  offset := %field%
      ifEqual, offset, ,return A_ThisFunc ": Invalid field name - " field

      v := NumGet(GLOBAL, offset, t=".1" ? "UChar" : "Uint" )
      if InStr(field, "al") {
         v%a_index% := ""
         loop, parse, alignments, %A_Space%
            if ( v & %A_LOOPFIELD% )
               v%a_index% .= A_LOOPFIELD " "
      } else
         v%a_index% := v
   }
   return ERRORLEVEL
}


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 6th, 2010, 8:46 pm 
Offline

Joined: May 24th, 2006, 2:49 pm
Posts: 4511
Location: Belgrade
Thanks. I included your function into module repository.

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject: SS_SetCell bug
PostPosted: July 9th, 2010, 11:30 pm 
Offline

Joined: October 4th, 2006, 2:15 am
Posts: 250
Location: Louisville, KY
I've found another bug in SS_SetCell, or at least it doesn't work quite as I expected and I like the way it works better with my fix. :)

As it was, there were several problems. First, it wasn't possible to set a text button column to an empty value. If you tried, you'd get a if a ^N char (0xE) value instead. Not entirely sure why that particular value, but that's what I got. I could set the cell to a space, but not a true empty string.

Second, if a cell utilitized it's txt attribute, it wasn't possible to set discrete cell attributes without supplying the text value too. For instance, if I tried to change a cell's foreground or background color, I had to fetch it's text value first and pass it along to SetCell. If not, I'd end up with "~`a " as the value in the field.

Finally, it wasn't possible to programmatically clear a text cell. If it have a value and you tried to clear the txt attribute (i.e. "txt="), it just stayed set to original value.

The problem comes from the initialization of the local var txt in the SetCell routine. It's initialized to "~`a " token value, I suppose to distinguish between an empty value and one not passed at all, but when checking to see if the txt attrib of the cell needs to be set, the logic checked for txt!="" instead of the token value. Thus the SPRIF_DATA bit was always set even if the user didn't supply a value.

Below I've changed the single line that sets the SPRIF_DATA bit in the flag var to check for the token value instead. Now it works like I'd expect and I haven't seen any unintended consequences.

As before, I've added a some line breaks in the static declarations to keep the code from forcing a wide message.

Code:
SS_SetCell(hCtrl, Col="", Row="", o1="", o2="", o3="", o4="", o5="", o6="", o7="", o8="", o9="", o10="", o11=""){
   static SPRM_SETCELLDATA=0x483, SPRM_GETCELLDATA=0x482, SPRM_GETCELLTYPE=0x48F
        , WM_DRAWITEM := 0x02B, initOverDraw
   static EMPTY=0, COLHDR=1, ROWHDR=2, WINHDR=3, TEXT=4, TEXTMULTILINE=5, INTEGER=6
        , FLOAT=7, FORMULA=8, GRAPH=9, HYPERLINK=10, CHECKBOX=11, COMBOBOX=12
        , OWNERDRAWBLOB=13, OWNERDRAWINTEGER=14, BUTTON=16, WIDEBUTTON=0x20, DATE=0x30
        , FORCETEXT=0x44, FORCETYPE=0x40, FIXEDSIZE=0x80
   static SPRIF_TYPE=0x40,SPRIF_DATA=0x200,SPRIF_WIDTH=0x80,SPRIF_BACKCOLOR=1
        ,SPRIF_TEXTCOLOR=2,SPRIF_TEXTALIGN=4,SPRIF_HEIGHT=0x100,SPRIF_STATE=0x20
        ,SPRIF_FONT=0x10,SPRIF_IMAGEALIGN=8,SPRIF_COMPILE=0x80000000, SPRIF_DOUBLE=0x400
        ,SPRIF_SINGLE=0x800
   static TOP=0, LEFT=0x10, CENTER=0x20, RIGHT=0x30, MIDDLE=0x40, BOTTOM=0x80
        , GLOBAL=0xF0, ALL=13, SCI=14      ;aligments
   static LOCKED=1, HIDDEN=2, REDRAW=8

  ;named parameters:  txt, data, w, h, bg, fg, type, state, txtal, imgal, fnt
   txt := "~`a "
   loop, 10 {
      ifEqual, o%A_Index%,,break
      j := InStr( o%A_index%, "=" ),    prop := SubStr(   o%A_index%, 1, j-1 ), %prop% := SubStr( o%A_index%, j+1, StrLen(o%A_Index%))
      if prop in type,state,imgal,txtal
      {
         p := "h" prop,  s := %prop%,  %p% := 0
         loop, parse, s, %A_Tab%%A_Space%
            if A_LoopField is integer
                %p% |= A_LoopField
            else %p% |= %A_LOOPFIELD%
      }
   }
    flag := 0
    ,flag |= (data!=""||txt!="~`a ") ? SPRIF_DATA  : 0
    ,flag |= (type!="")   ? SPRIF_TYPE      : 0
    ,flag |= (w != "")      ? SPRIF_WIDTH      : 0
    ,flag |= (h != "")      ? SPRIF_HEIGHT      : 0
    ,flag |= (bg!= "")      ? SPRIF_BACKCOLOR   : 0
    ,flag |= (fg!= "")      ? SPRIF_TEXTCOLOR   : 0
    ,flag |= (state !="")   ? SPRIF_STATE      : 0
    ,flag |= (txtal != "")   ? SPRIF_TEXTALIGN   : 0
    ,flag |= (imgal != "")   ? SPRIF_IMAGEALIGN   : 0
    ,flag |= (fnt != "")   ? SPRIF_FONT      : 0

   VarSetCapacity(ITEM, 40, 0), NumPut(Col, ITEM, 4),  NumPut(Row, ITEM, 8)
   if type =               ;user is changing the cell
   {
      bChange := true
      SendMessage,SPRM_GETCELLTYPE,Col,Row,, ahk_id %hCtrl%
      hType := ErrorLevel
   }

   type := hType & ~0xF0      ;get the base type
   if type in %FORMULA%,%GRAPH%
      flag |= SPRIF_COMPILE

   if type = %FLOAT%
      flag |= SPRIF_SINGLE,  NumPut(txt, txt, 0, "Float")

   if type in %INTEGER%,%OWNERDRAWINTEGER%
      NumPut(txt,txt)

   if type in %OWNERDRAWINTEGER%,%OWNERDRAWBLOB%
   {
      if !initOverDraw
      {
         old := OnMessage(WM_DRAWITEM, "SS_onDrawItem")
         if old != SS_onDrawItem
            SS("oldDrawItem", RegisterCallback(old))
      }

      if type=%OWNERDRAWBLOB%
         data := StrLen(txt)+3         ;first word is size of the blob + 1 for \0 of txt.
   }

   if type in %COMBOBOX%,%CHECKBOX%,%OWNERDRAWBLOB%
   {
      ; in this case both txt and data must be set at the same time, so if user didn't provide one, get it.
      if (bChange && (txt="~`a " || data=""))
      {
         NumPut(SPRIF_DATA, ITEM)
         SendMessage,SPRM_GETCELLDATA,,&ITEM,, ahk_id %hCtrl%
         pData := NumGet(ITEM, 36)
         if (data != "")
             txt := type=COMBOBOX ? NumGet(pData+4) : SS_strAtAdr(pData + 4)
         else data := NumGet(pData,36)
      }
      ifEqual, txt, ~`a , SetEnv, txt

      if (type = COMBOBOX)
         NumPut(txt,txt)      ;put combobox handle as txt
      txt := "1234" txt,   NumPut(data, txt)         ;make the room for the data and insert index
   }

   NumPut(flag,  ITEM)
   NumPut(hState,ITEM, 14)
   ;FORMAT struct
   NumPut(bg,     ITEM, 16)
   NumPut(fg,     ITEM, 20)
   NumPut(htxtal,ITEM, 24,"UChar")
   NumPut(himgal,ITEM, 25,"UChar")
   NumPut(fnt,     ITEM, 26,"UChar")
   NumPut(hType, ITEM, 27,"UChar")
   NumPut(w,     ITEM, 28)
   NumPut(h,     ITEM, 32)
   NumPut(&txt,  ITEM, 36)

   SendMessage,SPRM_SETCELLDATA,,&ITEM,, ahk_id %hCtrl%
   return ErrorLevel
}


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 10th, 2010, 2:14 am 
Offline

Joined: May 24th, 2006, 2:49 pm
Posts: 4511
Location: Belgrade
It was a bug. Thx for report.

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
PostPosted: July 12th, 2010, 9:50 pm 
Offline

Joined: October 4th, 2006, 2:15 am
Posts: 250
Location: Louisville, KY
I've been working on upgrading an app to use the SS control and it posed a few challenges to me.
    I needed real combobox functionality, instead of the simple drop-downs the SS control provides.
    I needed right-click context menus, something the SS control doesn't support.
    I needed it to work with a tabbed interface and being a custom control the normal GUI doesn't handle it's hiding and unhiding, and ComboX gets a little squirrelly with tabs too.
    I wanted the user to be able to move between cells with tab & shift-tab

So, I finally got it to work and thought I'd post a little demo script that demonstrates what's necessary. It's a simple app with 2 tabs, has two ComboX controls integrated in the spreadsheet, and right-clicking a cell in the SS will activate it, as well as produce a context menu. Right-clicking a column or row header will highlight the entire column or row and display a context menu too.

There are a few things that could use some improvement. Just before posting this I realized that the keyboard's context menu button doesn't work - only right-clicking brings up the menu - and I don't have time to figure that out just yet. Also, I'd eventually like the logic that resizes the width of the combox's listview to account for a possible vertical scrollbar. Finally, I'd like to think the logic for determining which cell is right-clicked on could be simplified but I can't see any other way to do it with the API functions we have.

Anyway, hopefully this will help someone else that wants to use the SS control with similar functionality later.
Code:
; Demo of spreadsheet control using the ComboX control for true comboboxes,
; a handler to allow for context menus with awareness of the column and row the
; user clicks on, demonstrates how to hide and show the spreadsheet when used
; with a Tab control, and enables movement with the tab key.

#SingleInstance, force

   ; Setup handler for converting tab press to arrow keys for SS controls
   WM_KEYDOWN = 0x100
   OnMessage( WM_KEYDOWN, "CheckTab" )

   ; create a context menu
   Menu, ssContextMenu, Add, Show Cell Info,     ContextSSShowCellInfo
   Menu, ssContextMenu, Add, Show Column Info,   ContextSSShowColInfo

   Gui, +LastFound +Resize
   hwnd := WinExist()

   ; Add tab control
   Gui, Add, Tab2, w200 h180 gTabSwitch vMyTab, Tab 1|Tab 2

   ; Add spreadsheet control
   hSS := SS_Add(hwnd, 16, 30, 185, 140, "GRIDLINES CELLEDIT ROWSIZE COLSIZE STATUS", "SSHandler" )

   ; Subclass the spreadsheet control so we have have a custom handler to
   ; catch right-clicks
   Win_Subclass(hSS, "SS_wndProc")

   SS_SetFont(hSS, 0, "s9, MS Sans Serif")
   SS_SetColCount( hSS, 3 )
   SS_SetRowCount( hSS, 5 )
   hSS@colhdr := 0 ; use this var for storing a column header click
   hSS@rowhdr := 0 ; use this var for storing a row header click

   ; populate the spreadsheet
   SS_SetCell(hSS,0,0, "txtal=RIGHT", "w=25")
   SS_SetCell(hSS,1,0, "txt=Col 1", "txtal=LEFT", "w=52")
   SS_SetCell(hSS,2,0, "txt=Col 2", "txtal=LEFT", "w=52")
   SS_SetCell(hSS,3,0, "txt=Col 3", "txtal=LEFT", "w=52")
   SS_SetCell(hSS,1,1, "type=TEXT BUTTON FORCETYPE", "imgal=RIGHT", "txt=" )
   SS_SetCell(hSS,2,1, "type=TEXT BUTTON FORCETYPE", "imgal=RIGHT", "txt=" )
   SS_SetCell(hSS,3,1, "type=TEXT FORCETYPE", "txt=" )
   SS_SetCell(hSS,1,2, "type=TEXT BUTTON FORCETYPE", "imgal=RIGHT", "txt=" )
   SS_SetCell(hSS,2,2, "type=TEXT BUTTON FORCETYPE", "imgal=RIGHT", "txt=" )
   SS_SetCell(hSS,3,2, "type=TEXT FORCETYPE", "txt=" )
   SS_SetCell(hSS,1,3, "type=TEXT BUTTON FORCETYPE", "imgal=RIGHT", "txt=" )
   SS_SetCell(hSS,2,3, "type=TEXT BUTTON FORCETYPE", "imgal=RIGHT", "txt=" )
   SS_SetCell(hSS,3,3, "type=TEXT FORCETYPE", "txt=" )
   SS_SetCell(hSS,1,4, "type=TEXT BUTTON FORCETYPE", "imgal=RIGHT", "txt=" )
   SS_SetCell(hSS,2,4, "type=TEXT BUTTON FORCETYPE", "imgal=RIGHT", "txt=" )
   SS_SetCell(hSS,3,4, "type=TEXT FORCETYPE", "txt=" )
   SS_SetCell(hSS,1,5, "type=TEXT BUTTON FORCETYPE", "imgal=RIGHT", "txt=" )
   SS_SetCell(hSS,2,5, "type=TEXT BUTTON FORCETYPE", "imgal=RIGHT", "txt=" )
   SS_SetCell(hSS,3,5, "type=TEXT FORCETYPE", "txt=" )

   ; Create the 2 ComboX controls
   Gui, Add, ListView, HWNDhlvcbx1 vlvcbx1 w50 h70 xs ys -Hdr -Multi Grid Sort, A
   FillTheList( "lvcbx1", "A1|B2" )
   ComboX_Set( hlvcbx1, "2LD esc space enter click ", "OnComboX")
   Win_SetOwner( hlvcbx1, hwnd ) ; necessary to hide lv child window

   Gui, Add, ListView, HWNDhlvcbx2 vlvcbx2 w50 h70 xs ys -Hdr -Multi Grid Sort, A
   FillTheList( "lvcbx2", "X|Y|Z" )
   ComboX_Set( hlvcbx2, "2LD esc space enter click ", "OnComboX")
   Win_SetOwner( hlvcbx2, hwnd ) ; necessary to hide lv child window

   Gui, Tab, Tab 2
   Gui, Add, GroupBox, Section        w178 h140, Notes
   Gui, Add, Edit,     xs+10  ys+20   w155 r8  veNotes,

   Gui, Show, h200 w220

   ; Hide the listviews initially
   ComboX_Hide(hlvcbx1)
   ComboX_Hide(hlvcbx2)
Return

ContextSSShowCellInfo:
   SS_GetCurrentCell( hSS, Col, Row )
   MsgBox Active Cell - Col: %col% Row: %Row%
return

ContextSSShowColInfo:
   SS_GetCurrentCell( hSS, Col, Row )
   MsgBox Right-clicked Column Header: %hSS@colhdr%
return

GuiClose:
   ExitApp

TabSwitch:
   ; When invoked, MyTab contains the name of the tab that has been deactivated

   ; Hide the SS control if moving off the tab containing it
   if ( MyTab = "Tab 1" ) {
      ; Since SS was on this tab, we need to make it invisible
      Win_Show( hSS, false )
   }

   ; Next, fetch the current value of MyTab.
   GuiControlGet, MyTab
   ; If switching to the tab containing the SS, show it.
   if ( MyTab = "Tab 1" ) {
      Win_Show( hSS, true )
      Gui, Show ; without this window is not active following Win_Show()

      ; Hide the ComboX list made active and visible when returning
      ; to the tab containing the controls
      ComboX_Hide(hlvcbx1)
      ComboX_Hide(hlvcbx2)
   }
return

OnComboX(hlv, Event) {
   global

   if (Event != "select")
      return
   if ( hlv = hlvcbx1 ) {
      Gui, ListView, lvcbx1 ; Set the listview to active
   } else if ( hlv = hlvcbx2 ) {
      Gui, ListView, lvcbx2 ; Set the listview to active
   }
   r :=  LV_GetNext()   ; Determine the selected item
   if r ; If we have a selected item...
   {
      LV_GetText( val, r, 1 )        ; Fetch it's value
      SS_SetCellString( hSS, val ) ; set the cell value
   }
}

FillTheList( p_list, p_values ) {
    Gui, Listview, %p_list%
    Loop, Parse, p_values, |
    {
       LV_Add("", A_LoopField )
    }
    LV_ModifyCol() ; Auto-size the listview's first column
}


SSHandler(hWnd, Event, EArg, Col, Row) {
   static i=0
   global hSS, hSS@colhdr, hSS@rowhdr, lvcbx1, lvcbx2

   if (    hWnd  = hSS ) {
      if ( Event = "C" ) { ; Clicked button so launch ComboX
         WinGetPos, x, y, ,
         ControlGetPos,ssx, ssy,,,, ahk_id %hSS% ; Get the x and y coords of the SS control
         SS_GetCellRect( hWnd, t, l, r, b )

         ; Fetch the column and listview width so we can display the listview,
         ; accounting for the cell width and user-supplied values.
         ; To Do: figure out whether the listview will use a vertical scroll bar
         ; and account for it's width too.
           width := SS_GetColWidth( hSS, col )
         lv_w  := LVM_GetColWidth( hlvcbx%col%, 1 )
         if ( width > lv_w )
            LV_ModifyCol( 1, width )
         else
            width := lv_w
         ComboX_Show( hlvcbx%col%, x+ssx+r-width+2, y+ssy+b, width)
      }
      ; Column selected via left-click or keyboard, so remove column or row highlight
      if ( Event = "S" ) {
           if ( hSS@colhdr > 0 )
              UnhighlightColumn( hSS, hSS@colhdr )
         ; if a row was previously highlighted, unhighlight it
           if ( hSS@rowhdr > 0 )
              UnhighlightRow( hSS, hSS@rowhdr )
      }
      ; Update comboX controls with new values after they've been keyed
      ; in manually.
      if (   Event = "UA"
         and Col in 1,2      ) {
         cell_value := SS_GetCellText( hSS, Col, Row )
         Gui, Listview, lvcbx%col%
           found := false
           Loop % LV_GetCount()
           {
              LV_GetText( item, A_Index )
              if ( item = cell_value )
                 found := true
           }
           if ( ! found ) {
              LV_Add("select focus", cell_value )
              LV_ModifyCol()
           }
      }
   }
}

ss_wndProc(Hwnd, UMsg, WParam, LParam) {
   global hSS, hSS@colhdr, hSS@rowhdr
   static i=0
   critical      ;safe, always in new thread

   if ( UMsg = 0x7B ) {  ; "WM_CONTEXTMENU"  - To Do: detect context menu button too.
      y := LParam>>16
      x := LParam & 0x0000FFFF + 0
      if CellHitTest( hSS, x, y, col, row ) { ; Determine what cell what clicked on and change focus
         ; if a column was previously highlighted, unhighlight it
           if ( hSS@colhdr > 0 )
              UnhighlightColumn( hSS, hSS@colhdr ), hSS@colhdr := 0
         ; if a row was previously highlighted, unhighlight it
           if ( hSS@rowhdr > 0 )
              UnhighlightRow( hSS, hSS@rowhdr ), hSS@rowhdr := 0
         ; if the row or col = 0, disable the cell info menu and highlight the row/column
         if ( row = 0 or col = 0 ) {
            Menu, ssContextMenu, Disable, Show Cell Info
            if ( row = 0 )
               hSS@colhdr := col ; User right-clicked a column header
            else
               HighlightRow( hSS, Row )
            if ( col = 0 )
               hSS@rowhdr := row ; User right-clicked a row header
            else {
               HighlightColumn( hSS, Col )
               Menu, ssContextMenu, Enable, Show Column Info
            }
         } else {
            Menu, ssContextMenu, Enable, Show Cell Info
         }
         if ( row > 0 and col = 0 )
            Menu, ssContextMenu, Disable, Show Column Info

         ; Finally, display the context menu
         CoordMode, Menu, Screen
         Menu, ssContextMenu, Show, %x%, %y%
         CoordMode, Menu, Relative
      }
      ; return without passing to SS control, else it passes msg to main window
      ; and that triggers the GuiContextMenu routine, without all the info needed
      ; to act on it.
      return 0
   } else
      ; Not a message we process, so pass the message to the default handler.
      res := DllCall("CallWindowProcA", "UInt", A_EventInfo, "UInt", hSS, "UInt", UMsg, "UInt", WParam, "UInt", LParam)
   return res

ss_wndProc:
return
}

HighlightColumn( hSS, Col, bg="0xFF", fg="0xFFFFFF" ) {
   Loop % SS_GetRowcount( hSS )
      SS_SetCell( hSS, Col, A_Index, "bg=" bg, "fg=" fg )
   SS_Redraw( hSS )
}

UnhighlightColumn( hSS, Col ) {
   SS_GetGlobalFields( hSS, "cell_fg cell_bg", fg, bg )
   Loop % SS_GetRowcount( hSS )
      SS_SetCell( hSS, Col, A_Index, "bg=" bg, "fg=" fg )
   SS_Redraw( hSS )
}

HighlightRow( hSS, Row, bg="0xFF", fg="0xFFFFFF" ) {
   Loop % SS_GetColCount( hSS )
      SS_SetCell( hSS, A_Index, Row, "bg=" bg, "fg=" fg )
   SS_Redraw( hSS )
}

UnhighlightRow( hSS, Row ) {
   SS_GetGlobalFields( hSS, "cell_fg cell_bg", fg, bg )
   Loop % SS_GetColCount( hSS )
      SS_SetCell( hSS, A_Index, Row, "bg=" bg, "fg=" fg )
   SS_Redraw( hSS )
}

CellHitTest( hSS, x, y, ByRef rtn_col="", ByRef rtn_row="", change_focus=true ){
   WinGetPos, wx, wy,,,A      ; Get the window coords
   ; Get the number of cols, rows and the header height and width
   SS_GetGlobalFields( hSS, "ncols nrows ghdrht ghdrwt", ncols, nrows, chdr_ht, rhdr_width )

   ControlGetPos,ssx, ssy,,,, ahk_id %hSS% ; Get the x and y coords of the SS control

   ; Convert the passed mouse x/y coords to  x/y coords within the SS control
   x -= ( wx + ssx )
   y -= ( wy + ssy )

   rtn_row := rtn_col := -1 ; Init to -1

   ; Check to see if the user has clicked in the row or column header.
   if ( y <= chdr_ht )
      rtn_row := 0, change_focus := false
   if ( x <= rhdr_width )
      rtn_col := 0, change_focus := false

   ; Now try to position the active cell under the mouse cursor.  We check to see if the
   ; mouse x/y coords fall within the current cell.  If not, we move the current cell
   ; in the direction of the mouse and check again until we either have either made the
   ; correct cell active, or determined that the coords are outside the area of the SS
   SS_GetCurrentCell( hSS, col, row ) ; Get and save current cell location
   starting_col := col, starting_row := row

   success := true
   Loop
   {
      SS_GetCellRect( hSS, top, left, right, bottom )
      if !(   x>right  or (x<left and rtn_col != 0)
           or y>bottom or (y<top  and rtn_row != 0) )
         break ; we're correctly positioned, so break out of the loop
      if ( x>right )
         col++   ; need to move to the right
      if ( x<left and rtn_col != 0 )
         col-- ; need to move to the left
      if ( y>bottom )
         row++ ; need to move down
      if ( y<top and rtn_row != 0 )
         row-- ; need to move up
      if ( col > 0 and col <= ncols and row > 0 and row <= nrows )
         ; if we're still within the spreadsheet, set the current cell
         SS_SetCurrentCell( hSS, col, row )
      else {
         success := false
         break
      }
   }
   if ( !success or !change_focus )
      SS_SetCurrentCell( hSS, starting_col, starting_row ) ; reset to orig cell

   if ( success ) {
      if change_focus
         SS_Redraw( hss ) ; redraw the SS
      rtn_col := ( rtn_col = -1 and col > 0 ) ? col : rtn_col
      rtn_row := ( rtn_row = -1 and row > 0 ) ? row : rtn_row
   }
   return success
}

; h = ListView handle.
; c = 1 based column index to get width of.
LVM_GetColWidth(h, c)
{
   Return DllCall("SendMessage", "UInt", h, "UInt", 4125, "UInt", c-1, "UInt", 0) ; LVM_GETCOLUMNWIDTH
}

CheckTab( WParam,   LParam, UMsg, Hwnd )   {
   static WM_KEYDOWN   = 0x100,   VK_TAB=09, VK_RIGHT=0x27, VK_LEFT=0x25, VK_RETURN=0xD

   ControlGetFocus, Ctrl, A ;   get the name of the control currently in focus
   if   ( UMsg =   WM_KEYDOWN and   WParam =   VK_TAB )   {
      ; if the spreadsheet's edit control is active, end editing
      ; NOTE: The edit control's number - in this case 1 - is dependent on the
      ; number of other edit boxes in the GUI and order they're created
      if   ( Ctrl =   "Edit1" ) {
         PostMessage, WM_KEYDOWN, VK_RETURN,   ,%ctrl%
      }
      ; if the sheet control is focused, convert the tab to an arrow key
      if   ( Ctrl =   "SHEET_WIN1" )   {
         If   ( GetKeyState(   "Shift" ) )
            ; Send {Left}
            PostMessage, WM_KEYDOWN, VK_LEFT, ,%ctrl%
         else
            ; Send {Right}
            PostMessage, WM_KEYDOWN, VK_RIGHT, ,%ctrl%
      }
   }
}

#include SpreadSheet.ahk
#include ComboX.ahk


Last edited by wtg on July 13th, 2010, 8:46 pm, edited 3 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 13th, 2010, 9:09 am 
Offline

Joined: May 24th, 2006, 2:49 pm
Posts: 4511
Location: Belgrade
This is great sample. I might include it in the future distributions.

About your questions here is what I think about it: problem with keys could be easily solved by introducing hotkeys (so u could avoid subclassing).

About vertical scroll bar, there is a Windows API to know if windows has it, and u can get its dimensions. I think I did something similar in Scroller module.


Thanks wtg for your contributions.

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 118 posts ]  Go to page Previous  1 ... 4, 5, 6, 7, 8  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: specter333, XX0 and 25 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