nachdem ich mich mal wieder über mein altes Drag/Drop Modul geärgert habe
mußte ein Neues her.
Und zwar mit Image + Balken + Scrollen + alles viel besser
Leider mußte ich wieder feststellen, die Hilfe ist keine Hilfe was Drag Drop angeht.
Vor allem was da über die Callbacks steht ist mehr als mau, obermau, ja hypermau !!!!!!!
Allerdings die MSDN Hilfen sind auch nicht viel besser.
Zum Code. Wenn man den Teil mit dem Balken (InsertLine) + Scrollen etc weglässt, dann sollte man es auch CrossPlattform bekommen.
Aber das sollen andere machen.
Zuerst das Modul
Code: Alles auswählen
;LVDragDrop2020.pbi - Juni.2020 - by HJBremer
;Aufruf: ListIcon_EnableGadgetDrop(pbnr) pbnr vom ListIconGadget
; Entspricht PB Befehl EnableGadgetDrop() aber festgelegt auf #PB_Drop_Text und #PB_Drag_Copy
DeclareModule LvDragDrop
Declare.i ListIcon_EnableGadgetDrop(pbnr)
EndDeclareModule
Module LvDragDrop
EnableExplicit
Structure LVINSERTMARK ;muß Long sein !
cbSize.l
dwFlags.l
iItem.l
dwReserved.l
EndStructure
#PB_Drag_Typ = #PB_Drag_Copy
#itemEnd$ = #CRLF$ ;sollte nie nur #CR$ sein, wegen MultiLine-Items
Global dragfontid = FontID(LoadFont(#PB_Any, "Arial", 11)) ;für CreateDragImage()
Global cursorHand = LoadCursor_(0, #IDC_HAND) ;für anderen Cursor
Global sourceGadget = -1 ;Quelle
Global dragdropText$ ;DragText
Global dragLineFlag ;Balken oben oder unten
Global dragImageflag ;steuert Image Update
Global showanzchr = 100 ;Anz Char im Image
;werden einmalig festgelegt in ListIcon_EnableGadgetDrop()
Global mainwindow ;
Global dragwindow = -1 ;wird bewegt, enthält Image. -1 bedeutet gibts noch nicht
Global dragGadget ;PbNr vom ImageGadget im dragwindow
Procedure.i Drag_AddSelectedItems(pbnr, posi)
Protected j, item$
Protected drop$ = EventDropText()
Protected count = CountString(drop$, #itemEnd$)
ReplaceString(drop$, #TAB$, #LF$, #PB_String_InPlace) ;aus #Tab wird #LF
For j = 1 To count
item$ = StringField(drop$, j, #itemEnd$)
AddGadgetItem(pbnr, posi, item$) ;wenn posi -1 dann bleibt posi -1 = ans Ende
If posi <> -1 : posi + 1 : EndIf ; sonst posi + 1
Next
EndProcedure
Procedure.s Drag_GetSelectedItems(pbnr)
Protected item = -1, subitem, txt$ = ""
Protected hwnd = GadgetID(pbnr)
Protected hdid = SendMessage_(hwnd, #LVM_GETHEADER, 0, 0)
Protected cols = SendMessage_(hdid, #HDM_GETITEMCOUNT, 0, 0)
Repeat
item = SendMessage_(hwnd, #LVM_GETNEXTITEM, item, #LVNI_SELECTED)
If item <> -1
For subitem = 0 To cols
txt$ + GetGadgetItemText(pbnr, item, subitem) + #TAB$ ; Tab für z.B. Excel
Next
txt$ + #itemEnd$
EndIf
Until item = -1
ProcedureReturn txt$
EndProcedure
Procedure.i Drag_CreateImage(text$)
Protected imgw, imgh
Protected t1$, tw, th, ab = 22 ;ab ist Abstand Text vom PlusZeichen
Static dragImageNumber ;für FreeImage, muß Static sein
ReplaceString(text$, #TAB$, " ", #PB_String_InPlace)
t1$ = RTrim(StringField(text$, 1, #itemEnd$))
ReplaceString(t1$, #CR$, " ", #PB_String_InPlace)
If Len(t1$) > showanzchr: t1$ = Left(t1$, showanzchr) + "...": EndIf
If IsImage(dragImageNumber): FreeImage(dragImageNumber): EndIf
;Größe vom Image
dragImageNumber = CreateImage(#PB_Any, 1, 1)
StartDrawing(ImageOutput(dragImageNumber))
DrawingFont(dragfontid)
tw = TextWidth(t1$): th = TextHeight(text$)
imgw = tw + 6 + ab : imgh = th + 6
StopDrawing()
ResizeImage(dragImageNumber, imgw, imgh)
ResizeWindow(dragwindow, 0, 0, imgw, imgh)
;Image
StartDrawing(ImageOutput(dragImageNumber))
Box(0, 0, imgw, imgh, #Gray)
Box(1, 1, imgw-2, imgh-2, #Yellow)
DrawingMode(#PB_2DDrawing_Transparent)
DrawingFont(dragfontid)
DrawText(5, 2, "+", #Red): DrawText(ab, 2, t1$, #Black)
StopDrawing()
SetGadgetState(dragGadget, ImageID(dragImageNumber))
EndProcedure
Procedure.i Drag_Event()
;für #PB_Event_Gadget + #PB_EventType_DragStart
sourceGadget = EventGadget()
dragdropText$ = Drag_GetSelectedItems(sourceGadget)
Protected ok = DragText(dragdropText$, #PB_Drag_Typ) ;Startet Drag & Drop !!!!!
If ok = 0 ;Drag abgebrochen
dragImageflag = #PB_Drag_None ;Reset flag, sonst wird Image nicht aktualisiert
sourceGadget = -1
EndIf
EndProcedure
Procedure.i Drop_Event()
;für #PB_Event_GadgetDrop
Protected dropGadget = EventGadget()
Protected dropitem = -1
dropitem = SendMessage_(GadgetID(dropGadget), #LVM_GETNEXTITEM, dropitem, #LVNI_FOCUSED)
If dropitem <> -1
If dragLineFlag: dropitem + 1: EndIf ;wenn #true unter dem markierten Item einsetzen
EndIf
Drag_AddSelectedItems(dropGadget, dropitem)
sourceGadget = -1 ;letzte Drag/Drop Aktion, darum hier auf -1
EndProcedure
Procedure.i Drag_CallBack(action)
If action
Protected x = WindowMouseX(mainwindow) ;wo ist Cursor in diesem Programm
Protected y = WindowMouseY(mainwindow)
If Bool(x = -1 And y = -1) ;Maus ausserhalb vom Mainwindow
SetCursor_(0) ;eigenen Cursor löschen
ProcedureReturn 1 ;PB setzt den Standard-Cursor
Else
ProcedureReturn 0 ;Standard-Cursor ist weg, eigener Cursor wird
EndIf ; in DropCallback()/#PB_Drag_Enter gesetzt
EndIf
ProcedureReturn 1
EndProcedure
Procedure.i Drop_Callback(gadgethwnd, status, format, action, mouseX, mouseY)
;gadgethwnd = Quelle und/oder Ziel
;Variablen werden in #PB_Drag_Enter und in #PB_Drag_Update gebraucht darum Static
Static firstitem, lastitem ;für Scroll LineUp/Down
Static listhh ;für Scroll Down
Static rect.rect, hwndhead, headhh, itemhh ;für INSERTMARK-Line
Protected mousePos.POINT ;für INSERTMARK-Line
Protected lvInsertMark.LVINSERTMARK ;für INSERTMARK-Line
Protected x, y ;für ImageWindow anzeigen
Select status
Case #PB_Drag_Enter
;Vorgaben
firstitem = 0: lastitem = SendMessage_(gadgethwnd, #LVM_GETITEMCOUNT, 0, 0) - 1
hwndhead = SendMessage_(gadgethwnd, #LVM_GETHEADER, 0, 0)
SendMessage_(hwndhead, #HDM_GETITEMRECT , 0, rect): headhh = rect\bottom - rect\top
GetWindowRect_(gadgethwnd, rect) : listhh = rect\bottom - rect\top ;Quelle oder Ziel
rect\left = #LVIR_BOUNDS
SendMessage_(gadgethwnd, #LVM_GETITEMRECT, 0, rect) : itemhh = rect\bottom - rect\top
SetCursor_(cursorHand)
ShowWindow_(WindowID(dragwindow), #SW_SHOWNOACTIVATE) ;das Mainwindow bleibt aktiv
Case #PB_Drag_Update
;-- Liste scrollen up/down
If mouseY < 10
SendMessage_(gadgethwnd, #WM_VSCROLL, #SB_PAGEUP , 0) ;returns #false = null
ElseIf mouseY < 25
SendMessage_(gadgethwnd, #WM_VSCROLL, #SB_LINEUP , 0)
If SendMessage_(gadgethwnd, #LVM_ISITEMVISIBLE, firstitem , 0) = #True
SendMessage_(gadgethwnd, #LVM_ENSUREVISIBLE, firstitem , #False)
EndIf
ElseIf mouseY > listhh - 20
SendMessage_(gadgethwnd, #WM_VSCROLL, #SB_PAGEDOWN , 0)
ElseIf mouseY > listhh - 35
SendMessage_(gadgethwnd, #WM_VSCROLL, #SB_LINEDOWN , 0)
If SendMessage_(gadgethwnd, #LVM_ISITEMVISIBLE, lastitem , 0) = #True
SendMessage_(gadgethwnd, #LVM_ENSUREVISIBLE, lastitem , #False)
EndIf
EndIf
;-- Insert-Line anzeigen
lvInsertMark\cbSize = SizeOf(LVINSERTMARK)
mousePos\x = mousex ;pos innerhalb des Gadgets
mousePos\y = mousey
SendMessage_(gadgethwnd, #LVM_INSERTMARKHITTEST, mousePos, lvInsertMark)
SendMessage_(gadgethwnd, #LVM_SETINSERTMARK, 0, lvInsertMark)
dragLineFlag = 0
If (mousePos\y - headhh) % itemhh > itemhh / 2 : dragLineFlag = 1 : EndIf
;-- Image Create + anzeigen
;wenn Daten von Fremdprogramm ist sourceGadget = -1
If IsGadget(sourcegadget) = 0: dragdropText$ = "?": action = #PB_Drag_Copy : EndIf
If action <> #PB_Drag_None
Select action
Case #PB_Drag_Copy
If dragImageflag <> action ;verhindert mehrfaches Erstellen des Image
dragImageflag = action
Drag_CreateImage(dragdropText$)
EndIf
EndSelect
x = DesktopMouseX() + 20 ;Pluswerte gross genug, damit kein Leave entsteht, wenn
y = DesktopMouseY() + 14 ; Maus schnell bewegt wird. Cursor berührt ImageWindow
ResizeWindow(dragwindow, x, y, #PB_Ignore, #PB_Ignore)
EndIf
Case #PB_Drag_Leave
HideWindow(dragwindow, 1)
lvInsertMark\cbSize = SizeOf(LVINSERTMARK)
lvInsertMark\iItem = -1
SendMessage_(gadgethwnd, #LVM_SETINSERTMARK, 0, lvInsertMark) ;InsertMark weg
Case #PB_Drag_Finish
HideWindow(dragwindow, 1)
dragImageflag = #PB_Drag_None ;Flag Reset, sonst wird Image nicht aktualisiert
EndSelect
ProcedureReturn #True
EndProcedure
Procedure.i ListIcon_EnableGadgetDrop(pbnr)
Protected flags, old, mainWinId = GetAncestor_(GadgetID(pbnr), #GA_ROOT)
mainwindow = GetProp_(mainWinId, "PB_WINDOWID") - 1
EnableGadgetDrop(pbnr, #PB_Drop_Text, #PB_Drag_Typ)
SetDragCallback(@Drag_Callback())
SetDropCallback(@Drop_Callback())
BindEvent(#PB_Event_Gadget, @Drag_Event(), mainwindow, pbnr, #PB_EventType_DragStart)
BindEvent(#PB_Event_GadgetDrop, @Drop_Event(), mainwindow, pbnr)
If IsWindow(dragwindow) = 0 ;ist null wenn noch nicht existiert da Vorgabe -1
flags = #PB_Window_BorderLess|#PB_Window_NoGadgets|#PB_Window_Invisible|#PB_Window_NoActivate
dragwindow = OpenWindow(#PB_Any, 0, 0, 0, 0, "", flags, WindowID(mainwindow))
old = UseGadgetList(WindowID(dragwindow))
dragGadget = ImageGadget(#PB_Any,0,0,0,0,0)
UseGadgetList(old)
EndIf
EndProcedure
EndModule
UseModule LvDragDrop