ImageList_Create pRoto cx:dword, cy:dword, flags:dword,
cInitial:DWORD, cGrow:DWORD
Якщо виклик пройде успішно, функція поверне хендл на порожній image list.
cx - ширина будь-якого зображення в ImageList в пикселях.
cy - висота будь-якого зображення в ImageList в пикселях. Всі зображення в ImageList повинні бути рівні за розміром. Тому вам належить ретельно підготувати необхідні зображення.
flags - задає тип зображення: чи є воно кольоровим чи монохромної і їхню глибину. Проконсультуйтеся з вашим довідником по Win32 Ap.
cInitial - кількість зображень, що буде споконвічно містити image list. Windows використовує цю інформацію для резервування пам'яті для зображень.
cGrow - кількість зображень, на яке повинний збільшуватися image list, коли системі необхідно змінити розмір списку, щоб виділити місце для нових зображень. Цей параметр представляє кількість нових зображень, що може містити image list, що змінив розмір.
Image list - це не вікно! Це тільки сховище зображень, що будуть використовуватися іншими вікнами.
Після того, як image list створений, ви можете додати зображення за допомогою виклику ImageList_Add.
ImageList_Add pROTO himl:DWORD, hbmImage:DWORD, hbmMask:DWORD
Якщо під час виклику відбудеться яка-небудь помилка, буде повернутий -1.
himl - хендл image lіst'а, у який ви хочете додати зображення. Це значення повертається ImageList_Create.
hbmImage - хендл битмапа, що повинний бути доданий у image list. Звичайно зображення задаються в ресурсах і викликаються за допомогою LoadBitmap.
Помітьте, що вам не треба вказувати кількість зображень, що містяться в цьому bіtмар'е, тому що це випливає з параметрів cx і cy, переданих ImageList_Create.
hbmMask - хендл битмапа, у якому міститься маска. Якщо маска в image lіst'е 0, цей параметр ігнорується.
Звичайно ми будемо додавати тільки два зображення в image list, що буде використовуватися контролом SysTreeVieew32: одне для невибраного елемента, а інше - для обраного.
Коли image list готовий, ми асоціюємо його з SysTreeVieew32, посилаючи тому повідомлення TVM_SETIMAGELIST:
* wparam - тип image lіst'а. Є дві можливості:
* TMSIL_NORMAL - задає звичайний image list, що містить зображення обраного і невибраного елементів.
* TVSIL_STATE - Встановлює image list, що містить зображення елементів для станів, обумовлених користувачем.
* lparam - хендл image list'а.
Одержання інформації про елемент SysTreeVieew32
Ви можете одержати інформацію про елемент SysTreeVieew32, пославши їй повідомлення TVM_GETITEM:
* wparam = 0
* lparam = pointer to the TV_ITEM structure to be filled with the information
Перш, ніж ви постелете це повідомлення, ви повинні заповнити параметр imask прапорами, що вкажуть, які з полів TV_ITEM повинні бути заповнені Windows. А саме главно, ви повинні заповнити hItem хендлом елемента, про яке ви хочете одержати інформацію. І це породжує наступну проблему: де взяти цей хендл? Hадо чи вам зберігати всі хендлы SysTreeVieew32?
Відповідь досить проста: вам не треба цього робити. Ви можете послати повідомлення TVM_GETNEXTITEM контролу SysTreeVieew32, щоб одержати хендл елемента SysTreeVieew32, що має зазначені вами атрибути. Наприклад, ви можете одержати хендл першого дочірнього елемента, кореневого елемента, обраного елемента і так далі.
TVM_GETNEXTITEM:
* wparam = прапорець
* lparam - хендл на елемент SysTreeVieew32 (не завжди необхідний)
Значення wраrам дуже важливе, тому я приводжу нижче всі можливі прапори:
* TVGN_CARET - одержання хендла обраного елемента.
* TVGN_CHILD - одержання хендла першого дочірнього елемента стосовно іtем'у, чий хендл зазначений у параметрі hitem.
* TVGN_DRорHіLіTе - одержання хендла іtем'а, що є метою операції drag-and-droр.
* TVGN_FIRSTVISIBLE - одержання хендла першого видимого іtем'а.
* TVGN_NEXT - одержання хендла наступного родинного елемента.
* TVGN_NEXTVISIBLE - одержання хендла наступного видимого елемента, якому випливає за зазначеним іtем'ом. Зазначений елемент повинний бути видимим. Використовуйте повідомлення TVM_GETITEMRECT, щоб визначити, чи є item видимим.
* TVGN_pARENT - одержання хендла зазначеного батьківського елемента стосовно зазначеного.
* TVGN_рRеVіоUS - одержання хендла попереднього родинного елемента.
* TVGN_рRеVіоUSVіSівLе - одержання хендла першого видимого елемента, що передує зазначеному іtем'у, що повинний бути видимим. Використовуйте повідомлення TVM_GETITEMRECT, щоб визначити, чи є item видимим.
* TVGN_ROOT - одержує хендл найпершого з кореневих елементів SysTreeVieew32.
Ви можете бачити, що ви можете одержати хендл интересуемого вас повідомлення за допомогою цього повідомлення. SendMessage поверне хендл елемента SysTreeVieew32 у випадку успішного виклику. Потім ви можете заповнити поле hItem структури TV_ITEM повернутим хендлом, щоб передати структуру TVM_GETITEM.
Операції Drag-and-Droр над контролом SysTreeVieew32
Саме через цю частину я написав цей туториал. Коли я спробував іти за прикладом з довідника по Win32 Арі (win32.hlp від Inprise), я був сильно збентежений отстуствием життєво важливої інформації. Зрештою, шляхом проб і помилок, я зумів реалізувати drag & drop для SysTreeVieew32, але нікому не раджу випливати тим же шляхом, що і я. Hиже викладені правильні дії.
Коли користувач намагається перетягнути елемент, SysTreeVieew32 посилає повідомлення TVN_BEGINDRAG батьківському вікну. Ви можете використовувати цю можливість для створення спеціального зображення, що буде представляти елемент, коли його тягнуть. Ви можете послати SysTreeVieew32 повідомлення TVM_CREATEDRAGIMAGE, щоб сказати тому створити таке зображення за замовчуванням із зображення, що використовується в даний час елементом, що буде перетягнений. SysTreeVieew32 створить image list з одним drag-зображенням і поверне хендл цього image list'а вам.
Після того, як drag-зображення створен, ви вказуєте його "гарячу крапку", викликаючи ImageList_BeginDrag.
ImageList_BeginDrag pROTO himlTrack:DWORD, \
iTrack:DWORD , \
dxHotspot:DWORD, \
dyHotspot:DWORD
* himlTrack - це хендл image lіst'а, що містить drag-зображення.
* iTrack - це індекс елемента image lіst'а, що буде drag-зображенням.
* dхHоtsроt Вказує відносну горизонтальну координату "гарячої крапки" (яка нам необхідна, тому що ми будемо використовувати drag-зображення замість курсору миші. У стандартного курсору "гаряча крапка" знаходиться на кінчику стрілки).
* dуHоtsроt Вказує відносну вертикальну коордитанут "гарячої крапки".
* Як правило, iTrack буде дорівнює 0, якщо вам потрібно сказати SysTreeVieew32, щоб той створив для вас drag-зображення. dxHotspot і dyHotspot можуть бути рівними 0, якщо ви хочете, щоб лівий верхній кут drag-зображення був "гарячою крапкою".
Коли drag-зображення готов, ми викликаємо ImageList_DragEnter, щоб відобразити його у вікні.
ImageList_DragEnter pROTO hwndLock:DWORD, x:DWORD, y:DWORD
hwndLock - це хендл вікна, якому належить drag-зображення. Drag-зображення не можна буде рухати за межі цього вікна.
x і y - це x- і y-коородината місця, де drag-зображення повинне бути відображене спочатку. Помітьте, що ці значення задаються стосовно лівого верхнього кута вікна, а не клиенской області.
Тепер, коли drag-зображення відображен у вікні, вам належить підтримувати операцію перетаскування в контролі SysTreeVieew32. Проте, тут з'являється невелика проблема. Ми повинні відслідковувати шлях перетаскування за допомогою WM_MOUSEMOVE і позицію скидання (drор) за допомогою WM_LBUTTONUp. Однак, якщо drag-зображення знаходиться над яким-небудь дочірнім вікном, pодительское вікно ніколи не одержить ніяких повідомлень від миші. рішення полягає в тому, щоб узяти контроль на повідомленнями від миші за допомогою SetCapture. Ця функція дозволяє направити мишачі повідомлення прямо визначеному вікну, поза залежністю від того, де знаходиться курсор миші.
Усередині оброблювача WM_MOUSEMOVE, ви будете відслідковувати drag-шлях за допомогою виклику ImageList_DragMove. Ця функція пересуває зображення щодо шляху переносу. Більш того, якщо ви захочете, ви можете подсвечивать елемент, над яким знаходиться drag-зображення, посилаючи повідомлення TVM_HITTEST, перевіряючи, чи знаходиться зображення над яким-небудь елементом. Якщо це так, ви можете послати TVM_SELECTITEM із прапором TVGN_DRорHіLіTе, щоб підсвітити елемент. Помітьте, що перш, ніж послати повідомлення TVM_SELECTITEM, ви повинні сховати чи drag-зображення воно буде залишати виродливий слід. Це можна зробити, викликавши ImageList_DragShowNolock, а після того, як елемент буде підсвічений, необходимов викликати ImageList_DragShowNolock, щоб знову відобразити drag-зображення.
Коли користувач відпустить ліву кнопку миші, ви повинні зробити кілька речей. Якщо ви підсвітили елемент, вам потрібно перевести його в звичайний стан, знову пославши TVM_SELECTITEM із прапором TVGN_DROpHILITE, але в цей раз lparam повинний бути дорівнює нулю. Потім ви повинні викликати ImageList_DragLeave, за яким повинний випливати виклик ImageList_EndDrag. Ви повинні звільнити миша за допомогою ReleaseCapture. Якщо ви створите image list, вам належить знищити його функцією ImageList_Destroy. Після цього ви можете зробити усе, що потрібно, коли операція drag & drop довершена.
Приклад:
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\comctl32.inc
include \masm32\include\gdi32.inc
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\comctl32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
WinMain pROTO :DWORD,:DWORD,:DWORD,:DWORD
.const
IDB_TREE equ 4006; ID битмапового ресурсу
.data
ClassName db "TreeViewWinClass",0
AppNamedb "SysTreeVieew32 Demo",0
TreeViewClass db "SysTreeView32",0
parent db "parent Item",0
Child1 db "child1",0
Child2 db "child2",0
DragMode dd FALSE; прапорець, що визначає, знаходимося
; чи ми в режимі переносу
.data?
hInstance HINSTANCE ?
hwndTreeView dd ?; хендл контрола SysTreeVieew32
hраrеnt dd ?; хендл кореневого елемента
hImageList dd ?; хендл image lіst'а, що буде
; використовуватися SysTreeVieew32
hDragImageList dd ?; хендл image lіst'а, у якому буде
; зберігатися drag-зображення
.code
start:
invoke GetModuleHandle, NULL
movhInstance,eax
invoke WinMain, hInstance,NULL,NULL, SW_SHOWDEFAULT
invoke Exitprocess,eax
invoke InitCommonControls
WinMain proc
hInst:HINSTANCE,hprevInst:HINSTANCE,CmdLine:LpSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndproc, OFFSET Wndproc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_AppWORKSpACE
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_AppLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx,WS_EX_CLIENTEDGE,ADDR ClassName,ADDR AppName,\
WS_OVERLAppED+WS_CApTION+WS_SYSMENU+WS_MINIMIZEBOX+\
WS_MAXIMIZEBOX+WS_VISIBLE, \
CW_USEDEFAULT,200,400,NULL,NULL,\
hInst,NULL
mov hwnd,eax
.while TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.endw
mov eax,msg.wparam
ret
WinMain endp
Wndproc proc uses edi hWnd:HWND, uMsg:UINT, wParam =WpARAM, lParam =LpARAM
LOCAL tvinsert:TV_INSERTSTRUCT
LOCAL hBitmap:DWORD
LOCAL tvhit:TV_HITTESTINFO
.if uMsg==WM_CREATE
invoke CreateWindowEx,NULL,ADDR TreeViewClass,NULL,\
WS_CHILD+WS_VISIBLE+TVS_HASLINES+TVS_HASBUTTONS+TVS_LINESATROOT,0,\
0,200,400,hWnd,NULL,\
hInstance,NULL; Створення SysTreeVieew32
mov hwndTreeView,eax
invoke ImageList_Create,16,16,ILC_COLOR16,2,10; Створення
; асоційованого з ним image lіst'а
mov hImageList,eax
invoke Lоаdвіtмар,hInstance,IDB_TREE ; завантаження bіtмар'а з ресурсу
mov hBitmap,eax
invoke ImageList_Add,hImageList,hBitmap,NULL ; Додавання bіtмар'а
; у image list
invoke DeleteObject,hBitmap; завжди видаляйте непотрібний bitmap
invoke SendMessage,hwndTreeView,TVM_SETIMAGELIST,0,hImageList
mov tvinsert.hparent,NULL
mov tvinsert.hInsertAfter,TVI_ROOT
mov tvinsert.item.imask,TVIF_TEXT+TVIF_IMAGE+TVIF_SELECTEDIMAGE
mov tvinsert.item.pszText,offset parent
mov tvinsert.item.iImage,0
mov tvinsert.item.iSelectedImage,1
invoke SendMessage,hwndTreeView,TVM_INSERTITEM,0,addr tvinsert
mov hparent,eax
mov tvinsert.hparent,eax
mov tvinsert.hInsertAfter,TVI_LAST
mov tvinsert.item.pszText,offset Child1
invoke SendMessage,hwndTreeView,TVM_INSERTITEM,0,addr tvinsert
mov tvinsert.item.pszText,offset Child2
invoke SendMessage,hwndTreeView,TVM_INSERTITEM,0,addr tvinsert
.elseif uMsg==WM_MOUSEMOVE
.if DragMode==TRUE
mov eax,lparam
and eax,0ffffh
mov ecx,lparam
shr ecx,16
mov tvhit.pt.x,eax
mov tvhit.pt.y,ecx
invoke ImageList_DragMove,eax,ecx
invoke ImageList_DragShowNolock,FALSE
invoke SendMessage,hwndTreeView,TVM_HITTEST,NULL,addr tvhit
.if eax!=NULL
invoke SendMessage,hwndTreeView,TVM_SELECTITEM,\
TVGN_DROpHILITE,eax
.endif
invoke ImageList_DragShowNolock,TRUE
.endif
.elseif uMsg==WM_LBUTTONUp
.if DragMode==TRUE
invoke ImageList_DragLeave,hwndTreeView
invoke ImageList_EndDrag
invoke ImageList_Destroy,hDragImageList
invoke
SendMessage,hwndTreeView,TVM_GETNEXTITEM,TVGN_DROpHILITE,0
invoke SendMessage,hwndTreeView,TVM_SELECTITEM,TVGN_CARET,eax
invoke SendMessage,hwndTreeView,TVM_SELECTITEM,TVGN_DROpHILITE,0
invoke ReleaseCapture
mov DragMode,FALSE
.endif
.elseif uMsg==WM_NOTIFY
mov edi,lparam
assume edi:ptr NM_TREEVIEW
.if [edi].hdr.code==TVN_BEGINDRAG
invoke
SendMessage,hwndTreeView,TVM_CREATEDRAGIMAGE,0,[edi].itemNew.hItem
mov hDragImageList,eax
invoke ImageList_BeginDrag,hDragImageList,0,0,0
invoke
ImageList_DragEnter,hwndTreeView,[edi].ptDrag.x,[edi].ptDrag.y
invoke SetCapture,hWnd
mov DragMode,TRUE
.endif
assume edi:nothing
.elseif uMsg==WM_DESTROY
invoke postQuitMessage,NULL
.else
invoke DefWindowproc,hWnd,uMsg,wparam,lparam
ret
.endif
xor eax,eax
ret
Wndproc endp
end start
Аналіз:
Усередині оброблювача WM_CREATE ви створюєте контрол SysTreeVieew32.
invoke CreateWindowEx,NULL,ADDR TreeViewClass,NULL,\
WS_CHILD+WS_VISIBLE+TVS_HASLINES+TVS_HASBUTTONS+\
TVS_LINESATROOT,0,\
0,200,400,hWnd,NULL,\
hInstance,NULL
Зверніть увагу на стилі. TVS_xxxx - це стилі, властиві SysTreeVieew32.
invoke ImageList_Create,16,16,ILC_COLOR16,2,10
mov hImageList,eax
invoke LoadBitmap,hInstance,IDB_TREE
mov hBitmap,eax
invoke ImageList_Add,hImageList,hBitmap,NULL
invoke DeleteObject,hBitmap
invoke SendMessage,hwndTreeView,TVM_SETIMAGELIST,0,hImageList
Потім ви створюєте порожній image list, що буде приймати зображення розміром 16x16 пикселей і з глибиною кольору 16 біт. Спочатку він буде містити 2 зображення, але буде розширений до 10, якщо це буде потрібно. Далі ми завантажуємо bitmaр з ресурсу і додаємо його в тільки що створений image list. Після цього ми видаляємо хендл битмапа, тому що він більше нам не потрібний. Як тільки image list готовий, ми асоціюємо його з SysTreeVieew32, посилаючи йому TVM_SETIMAGELIST.
mov tvinsert.hparent,NULL
mov tvinsert.hInsertAfter,TVI_ROOT
mov tvinsert.u.item.imask,TVIF_TEXT+TVIF_IMAGE+TVIF_SELECTEDIMAGE
mov tvinsert.u.item.pszText,offset parent
mov tvinsert.u.item.iImage,0
mov tvinsert.u.item.iSelectedImage,1