forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   PureBasic (http://forum.boolean.name/forumdisplay.php?f=90)
-   -   Редактор таблицы (http://forum.boolean.name/showthread.php?t=17602)

Izunad 08.12.2012 01:08

Редактор таблицы
 
Здраствуйте. Можно ли посредством элемента ListIconGadget() создать более менее примитивный редактор таблиц???
Задача редактировать текст в выделенной строке. Есть мысль вызывать элемент StringGadget, но это звучит не по взрослому.

Izunad 08.12.2012 02:56

Ответ: Редактор таблицы
 
Хотя все очень по взрослому, туда можно впихать любые елементы. Но есть один нюанс, в елемент StringGadget() с флагом #PB_String_Numeric нельзя вписать дробное число.

Пётр 10.12.2012 16:23

Ответ: Редактор таблицы
 
Код:

;'Edit ListIcon'.
;-----------------
;  Stephen Rodriguez.
;  Created with Purebasic 4.02 for Windows (date:  May 2007).
;  Maintained with PB 4.2.

;  Platforms:  Windows (tested on XP and Vista 32-bit).

;  Licence: DAYLike
;    (Do As You Like with it! - No Warranties!)
;    A credit to myself, whilst nice, is not absolutely necessary.

;*******************************************************************************************

;NOTES.
;------
; 1)  Register a listicon gadget to have editable cells by using the command SetListIconEditable(listID).
;    You MUST set up such listicons to have a column zero of zero width.
; 2)  Cells are made editable by intercepting double-clicks, setting the #LVS_EDITLABELS style,
;    repositioning the edit control which Windows uses to edit the labels in column zero and copying
;    the resulting text to the listicon cell.
; 3)  Cells can also be edited by means of the command EditCell().
;*******************************************************************************************

#LVM_SUBITEMHITTEST = #LVM_FIRST+57
#LVM_GETSUBITEMRECT = #LVM_FIRST+56
#LVM_GETHEADER = #LVM_FIRST+31
#HDI_ORDER        = $80
#EC_RIGHTMARGIN = 2

EnableExplicit

CompilerIf Defined(HDITEM, #PB_Structure) = 0
  Structure HDITEM
    mask.l
    cxy.l
    pszText.l
    hbm.l
    cchTextMax.l
    fmt.l
    lParam.l
    iImage.l
    iOrder.l
  EndStructure
CompilerEndIf

Structure _LIEdit
  listOldProc.l
  editHwnd.l
  item.l
  subitem.l
  x.l
  y.l
  cx.l
  cy.l
  osVersion.b
  blnIsXPThemes.b
EndStructure

Structure _LIEditGlobals
  osVersion.b
  blnIsXPThemes.b
EndStructure

Declare.l SetListIconEditable(listID)
Declare _LIEEditCell(*liedit._LIEdit, hWnd)
Declare.l _LIEwinProc(hWnd, uMsg, wParam, lParam)
Declare.l _LIEListProc(hWnd, uMsg, wParam, lParam)
Declare.l _LIEeditProc(hWnd, uMsg, wParam, lParam)

Global _LIEditGlobals._LIEditGlobals

;Returns zero if an error.
Procedure.l SetListIconEditable(listID)
  Protected result, parenthWnd, *mem._LIEdit, hWnd, dlv.DLLVERSIONINFO, func, lib
  ;Set globals if appropriate.
    If _LIEditGlobals\osVersion = 0
      _LIEditGlobals\osVersion = OSVersion()
      dlv\cbSize=SizeOf(DLLVERSIONINFO)
      lib=OpenLibrary(#PB_Any,"comctl32.dll")
      If lib
        func=GetFunction(lib,"DllGetVersion")
        If func
          CallFunctionFast(func, dlv)
          If dlv\dwMajorVersion >=6
            _LIEditGlobals\blnIsXPThemes = #True
          EndIf           
        EndIf
        CloseLibrary(lib)
      EndIf
    EndIf
  ;Check that listID references a valid listicon.
    If IsGadget(listID) And GadgetType(listID)=#PB_GadgetType_ListIcon
      hWnd = GadgetID(listID)
      ;Is the listicon already registered?
      If GetProp_(hWnd, "_LIEdit")=0 ;No!
        ;Allocate enough memory for a _LIEdit structure.
          *mem=AllocateMemory(SizeOf(_LIEdit))
        If *mem
          SetWindowLong_(hWnd, #GWL_STYLE, GetWindowLong_(hWnd, #GWL_STYLE)&~#LVS_EDITLABELS)
          ;Set the fields of the _LIEedit structure.
            *mem\listOldProc = SetWindowLong_(hWnd, #GWL_WNDPROC, @_LIEListProc())
          ;Store a pointer to this structure in a window property ofthe listicon.         
            SetProp_(hWnd, "_LIEdit", *mem)
          ;Subclass the parent window if not already through another listicon.
            parenthWnd=GetParent_(hWnd)
            If GetProp_(parenthWnd, "_LIEditOldProc")=0 ;No!
              SetProp_(parenthWnd, "_LIEditOldProc", SetWindowLong_(parenthWnd, #GWL_WNDPROC, @_LIEwinProc()))
            EndIf
          result=1
        EndIf
      EndIf
    EndIf
  ProcedureReturn result
EndProcedure


;Sets the specified cell to be edited.
Procedure EditCell(listID, item, subitem)
  Protected hWnd, *liedit._LIEdit, numrows, numcols
  ;Check that listID references a valid listicon.
    If IsGadget(listID) And GadgetType(listID)=#PB_GadgetType_ListIcon
      ;Check that the listicon is registered as editable.
        hWnd = GadgetID(listID)
        *liedit = GetProp_(hWnd, "_LIEdit")
        If *liedit
          ;Check parameters are in range.
            numrows = CountGadgetItems(listID)
            numcols = SendMessage_(SendMessage_(hWnd,#LVM_GETHEADER,0,0), #HDM_GETITEMCOUNT,0,0)
            If item>=0 And item < numrows And subitem>0 And subitem < numcols
              *liedit\item = item
              *liedit\subitem = subitem
              SetActiveGadget(listID)
              _LIEEditCell(*liedit, hWnd)
            EndIf
        EndIf
    EndIf
EndProcedure


Procedure _LIEEditCell(*liedit._LIEdit, hWnd)
  Protected rc.RECT, clientrc.RECT, numCols, headerWnd
  Protected Dim cols(0), i, blnFoundZeroColumn
  Protected hdi.HDITEM
  ;Vista themes requires a cheat because it automatically scrolls the listicon to bring the item being edited
  ;into view.
    If _LIEditGlobals\osVersion >= #PB_OS_Windows_Vista And _LIEditGlobals\blnIsXPThemes
      headerWnd = SendMessage_(hWnd,#LVM_GETHEADER,0,0)
      numCols = SendMessage_(headerWnd, #HDM_GETITEMCOUNT,0,0)
      Dim cols(numCols-1)
      SendMessage_(hWnd, #LVM_GETCOLUMNORDERARRAY, numCols, @cols())
      For i = 0 To numcols-1
        If cols(i)
          If cols(i) = *liedit\subItem
            Break
          EndIf
        Else
          blnFoundZeroColumn = 1     
        EndIf
      Next
      i-blnFoundZeroColumn
      Dim cols(0)
      With hdi
        \mask = #HDI_ORDER
        \iOrder = i
      EndWith     
      SendMessage_(headerWnd, #HDM_SETITEM, 0, hdi)
    EndIf
  ;Scroll the listicon if the clicked cell is not entirely visible
  ;*****IF YOU WISH TO RESTRICT WHICH CELLS CAN BE EDITED, THEN PERFORM THE NECESSARY CHECKS HERE
  ;*****ON THE VALUES OF *liedit\item and *liedit\subitem (WHICH INDICATE WHICH CELL IS ABOUT
  ;*****TO BE EDITED) AND RUN THE FOLLOWING LINES FOR THOSE CELLS WHICH ARE TO BE EDITED.
  rc\top = *liedit\subitem
  rc\left = #LVIR_BOUNDS
  SendMessage_(hWnd, #LVM_GETSUBITEMRECT, *liedit\item, rc)
  GetClientRect_(hWnd, clientrc)
  If rc\left < 0 Or (rc\right-rc\left)>=clientrc\right
    SendMessage_(hWnd, #LVM_SCROLL,rc\left,0)
  Else
    If rc\right > clientrc\right
      SendMessage_(hWnd, #LVM_SCROLL,rc\right-clientrc\right,0)
    EndIf
  EndIf
  SetWindowLong_(hWnd, #GWL_STYLE, GetWindowLong_(hWnd, #GWL_STYLE)|#LVS_EDITLABELS)
  SendMessage_(hWnd, #LVM_EDITLABEL, *liedit\item, 0)
EndProcedure


;Window proc of the ListIcon parent window.
Procedure.l _LIEwinProc(hWnd, uMsg, wParam, lParam)
  Protected result, oldwinproc, *nmh. NMHDR, listhWnd, edithWnd, *liedit._LIEdit, *lvd.LV_DISPINFO, rc.RECT
  Protected hdi.HDITEM, headerWnd
  Static celltext$
  ;Retrieve the address of the old proc.
    oldwinproc = GetProp_(hWnd, "_LIEditOldProc")
  Select uMsg
    Case #WM_NOTIFY
      *nmh=lParam
      Select *nmh\code
        Case #LVN_BEGINLABELEDIT
          listhWnd = *nmh\hwndFrom
          ;Retrieve the address of the LIEdit structure.
            *liedit = GetProp_(listhWnd, "_LIEdit")
            If *liedit ;Good to go!
              *liedit\editHwnd=0
              ;Get the handle of the edit control used to edit the label.
                edithWnd = SendMessage_(listhWnd, #LVM_GETEDITCONTROL,0,0)
              ;Subclass the edit control.
                SetProp_(edithWnd, "_LIEditOldProc", SetWindowLong_(edithWnd, #GWL_WNDPROC, @_LIEeditProc()))
              ;Set text.
                celltext$=GetGadgetItemText(*nmh\idFrom, *liedit\item, *liedit\subitem)
                SendMessage_(edithWnd, #WM_SETTEXT, 0, celltext$)
                SetGadgetItemText(*nmh\idFrom, *liedit\item, "",*liedit\subitem)
              ;Get bounding rectangle.
                rc\top = *liedit\subitem
                rc\left = #LVIR_BOUNDS
                SendMessage_(listhWnd, #LVM_GETSUBITEMRECT, *liedit\item, rc)
                *liedit\x=rc\left
                *liedit\y=rc\top
                *liedit\cx=SendMessage_(listhWnd, #LVM_GETCOLUMNWIDTH, *liedit\subitem,0)
                *liedit\cy=rc\bottom-rc\top
            EndIf

        Case #LVN_ENDLABELEDIT
          listhWnd = *nmh\hwndFrom
          ;Retrieve the address of the LIEdit structure.
            *liedit = GetProp_(listhWnd, "_LIEdit")
            If *liedit ;Good to go!
              *lvd = lParam
              If *lvd\item\pszText
                SetGadgetItemText(*nmh\idFrom, *liedit\item, PeekS(*lvd\item\pszText), *liedit\subitem)
              Else             
                SetGadgetItemText(*nmh\idFrom, *liedit\item, celltext$, *liedit\subitem)
              EndIf
              SetWindowLong_(listhWnd, #GWL_STYLE, GetWindowLong_(listhWnd, #GWL_STYLE)&~#LVS_EDITLABELS)
              If _LIEditGlobals\osVersion >= #PB_OS_Windows_Vista And _LIEditGlobals\blnIsXPThemes
                With hdi
                  \mask = #HDI_ORDER
                  \iOrder = 0
                EndWith
                headerWnd = SendMessage_(listhWnd,#LVM_GETHEADER,0,0)
                SendMessage_(headerWnd, #HDM_SETITEM, 0, hdi)
              EndIf
            EndIf
        Default
          result=CallWindowProc_(oldwinproc, hWnd, uMsg, wParam, lParam)
      EndSelect

    Case #WM_NCDESTROY
      result=CallWindowProc_(oldwinproc, hWnd, uMsg, wParam, lParam)
      RemoveProp_(hWnd, "_LIEditOldProc")
    Default
      result=CallWindowProc_(oldwinproc, hWnd, uMsg, wParam, lParam)
  EndSelect
  ProcedureReturn result
EndProcedure


;Window proc of the ListIcon.
Procedure.l _LIEListProc(hWnd, uMsg, wParam, lParam)
  Protected result, *liedit._LIEdit, PInfo.LVHITTESTINFO, *nmHEADER.HD_NOTIFY
  ;Retrieve the address of the LIEdit structure.
    *liedit = GetProp_(hWnd, "_LIEdit")
  Select uMsg
    Case #WM_NOTIFY
      *nmHEADER = lParam
      Select *nmHEADER\hdr\code
        Case #HDN_BEGINTRACK, #HDN_BEGINTRACKW ;Prevent column 0 from being resized.
          If *nmHEADER\iItem=0
            result=1
          EndIf
        Case #HDN_ENDTRACK, #HDN_ENDTRACKW
          InvalidateRect_(hWnd,0,1)
        Default
          result=CallWindowProc_(*liedit\listOldProc, hWnd, uMsg, wParam, lParam)
      EndSelect
    Case #WM_LBUTTONDBLCLK
      ;Identify the clicked item
        PInfo\pt\x = lParam&$ffff
        PInfo\pt\y = (lParam>>16)&$ffff
        SendMessage_(hwnd, #LVM_SUBITEMHITTEST, 0, PInfo)
      If PInfo\iItem <> -1 ;A valid cell was clicked.
        *liedit\item = PInfo\iItem
        *liedit\subitem = PInfo\iSubItem
        _LIEEditCell(*liedit, hWnd)
      EndIf
    Case #WM_NCDESTROY
      result=CallWindowProc_(*liedit\listOldProc, hWnd, uMsg, wParam, lParam)
      RemoveProp_(hWnd, "_LIEdit")
      FreeMemory(*liedit)
    Default
      result=CallWindowProc_(*liedit\listOldProc, hWnd, uMsg, wParam, lParam)
  EndSelect
  ProcedureReturn result
EndProcedure


;Window proc of the edit control.
Procedure.l _LIEeditProc(hWnd, uMsg, wParam, lParam)
  Protected result, oldwinproc, *liedit._LIEdit, *wpos.WINDOWPOS
  ;Retrieve the address of the old proc.
    oldwinproc = GetProp_(hWnd, "_LIEditOldProc")
  ;Retrieve the address of the LIEdit structure.
    *liedit = GetProp_(GetParent_(hWnd), "_LIEdit")
  Select uMsg
    Case #WM_ERASEBKGND
      ;A hack in order to clear the default selection of characters.
      result=CallWindowProc_(oldwinproc, hWnd, uMsg, wParam, lParam)
      If *liedit\editHwnd=0
        *liedit\editHwnd = hWnd
        ;Set margins.
        SendMessage_(hWnd, #EM_SETMARGINS, #EC_LEFTMARGIN|#EC_RIGHTMARGIN, 4)
        SendMessage_(hWnd, #EM_SETSEL, -1,0)
      EndIf
    Case #WM_WINDOWPOSCHANGING
      *wpos=lParam
      *wpos\cx=*liedit\cx ;Comment this line to get an edit control which grows with the text.
      *wpos\x=*liedit\x
      If _LIEditGlobals\osVersion >= #PB_OS_Windows_Vista And _LIEditGlobals\blnIsXPThemes
        *wpos\cy=*liedit\cy
        *wpos\y=*liedit\y
      Else
        *wpos\cy=*liedit\cy+3
        *wpos\y=*liedit\y-2
      EndIf
      result=CallWindowProc_(oldwinproc, hWnd, uMsg, wParam, lParam)
    Case #WM_NCDESTROY
      result=CallWindowProc_(oldwinproc, hWnd, uMsg, wParam, lParam)
      RemoveProp_(hWnd, "_LIEditOldProc")
      ;InvalidateRect_(GetParent_(hWnd),0,0)
    Default
      result=CallWindowProc_(oldwinproc, hWnd, uMsg, wParam, lParam)
  EndSelect
  ProcedureReturn result
EndProcedure


DisableExplicit

LoadFont(1, "Arial",10)

If OpenWindow(0, 100, 100, 600, 600, "ListIcon Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  If CreateGadgetList(WindowID(0))
    ListIconGadget(1, 5, 5, 490, 390, "", 0, #PB_ListIcon_GridLines|#PB_ListIcon_HeaderDragDrop)
    SetGadgetFont(1, FontID(1))
    For i = 1 To 30
      AddGadgetColumn(1, i, "Col "+Str(i), 100)
    Next
    For row = 1 To 100
      AddGadgetItem(1,-1,"")
      For col = 2 To 10
        SetGadgetItemText(1, row-1, "row "+Str(row-1)+", col "+Str(col), col)
      Next
    Next

    SetListIconEditable(1)
;    EditCell(1, 19, 5)
    Repeat
      Event = WaitWindowEvent()
    Until Event = #PB_Event_CloseWindow
  EndIf
EndIf



Часовой пояс GMT +4, время: 20:27.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot