navigation.cpp 79 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733
  1. #include "./navigation.h"
  2. #include "./ml.h"
  3. #include "./ml_ipc_0313.h"
  4. #include "../nu/AutoChar.h"
  5. #include "../nu/AutoWide.h"
  6. #include "./skinning.h"
  7. #include "./stockobjects.h"
  8. #include "../winamp/wa_dlg.h"
  9. #include "../winamp/gen.h"
  10. #include "resource.h"
  11. #include "api__gen_ml.h"
  12. #include "../nu/CGlobalAtom.h"
  13. #include "../nu/trace.h"
  14. #include <windowsx.h>
  15. #include <strsafe.h>
  16. extern "C" winampGeneralPurposePlugin plugin;
  17. #ifndef LONGX86
  18. #ifdef _WIN64
  19. #define LONGX86 LONG_PTR
  20. #else /*_WIN64*/
  21. #define LONGX86 LONG
  22. #endif /*_WIN64*/
  23. #endif // LONGX86
  24. #define PACKVERSION(major,minor) MAKELONG(minor,major)
  25. #define SEPARATOR L'/'
  26. #define MLV_PREFIX_A L"mlv10_"
  27. #define EMPTY_ITEM_NAME L"<<empty>>"
  28. #define ITEM_SHORTNAME_MAX 512
  29. #define SAVEVIEW_BUFFER_MAX 1024
  30. #define ML_VIEW_MAX 32
  31. #define NAVITEM_RANGE_MIN 8000
  32. static CGlobalAtom NAVMGR_HWNDPROPW(L"NAVMNGR");
  33. static CGlobalAtom WNDPROP_SCCTRLW(L"SCCTRL");
  34. #define IREC_COUNT 3
  35. #define IREC_NORMAL 0x00
  36. #define IREC_SELECTED 0x01
  37. #define IREC_INACTIVE 0x02
  38. #define DRAGIMAGE_OFFSET_X 8
  39. #define DRAGIMAGE_OFFSET_Y 0
  40. typedef struct _SCEDIT
  41. {
  42. WNDPROC fnOldProc;
  43. BOOL fUnicode;
  44. }SCEDIT;
  45. typedef struct _SCTREE
  46. {
  47. WNDPROC fnOldProc;
  48. BOOL fUnicode;
  49. DWORD focused;
  50. BOOL supressEdit;
  51. }SCTREE;
  52. typedef struct _NAVITEMSTATEREC
  53. {
  54. LPWSTR pszFullName;
  55. INT fCollapsed;
  56. INT nOrder;
  57. } NAVITEMSTATEREC;
  58. typedef struct _NAVMNGR
  59. {
  60. HWND hwndHost;
  61. INT lastUsedId;
  62. C_Config *pConfig;
  63. HMLIMGLST hmlilImages;
  64. INT lockUpdate;
  65. HTREEITEM lockFirst;
  66. HTREEITEM lockSelected;
  67. INT lockSelPos;
  68. INT lastOrderIndex;
  69. NAVITEMSTATEREC *pStates;
  70. INT statesCount;
  71. UINT style;
  72. NAVITEMDRAW_I drawStruct;
  73. HFONT hfontOld;
  74. UINT drawInternal;
  75. // callbacks
  76. ONNAVITEMCLICK_I fnOnItemClick;
  77. ONNAVITEMSELECTED_I fnOnItemSelected;
  78. ONNAVCTRLKEYDOWN_I fnOnKeyDown;
  79. ONNAVCTRLBEGINDRAG_I fnOnBeginDrag;
  80. ONNAVITEMGETIMAGEINDEX_I fnOnItemGetImageIndex;
  81. ONNAVITEMBEGINTITLEEDIT_I fnOnBeginTitleEdit;
  82. ONNAVCTRLENDTITLEEDIT_I fnOnEndTitleEdit;
  83. ONNAVITEMDELETE_I fnOnItemDelete;
  84. ONNAVITEMDRAW_I fnOnCustomDraw;
  85. ONNAVITEMSETCURSOR_I fnOnSetCursor;
  86. ONNAVITEMHITTEST_I fnOnHitTest;
  87. ONNAVCTRLDESTROY_I fnOnDestroy;
  88. } NAVMNGR, *PNAVMNGR;
  89. typedef struct _NAVITM
  90. {
  91. INT id;
  92. INT iImage;
  93. INT iSelectedImage;
  94. WORD sortOrder;
  95. UINT style;
  96. HWND hwndTree;
  97. HTREEITEM hTreeItem;
  98. LPWSTR pszText;
  99. INT cchTextMax;
  100. LPWSTR pszInvariant;
  101. INT cchInvariantMax;
  102. HFONT hFont;
  103. BOOL fBlockInvalid; // if set to TRUE operation do not need to inavlidate item it will be invalidated later;
  104. LPARAM lParam;
  105. } NAVITM, *PNAVITM;
  106. typedef struct _TREEITEMSEARCH
  107. {
  108. TVITEMEXW item;
  109. INT_PTR itemData;
  110. BOOL fFound;
  111. UINT flags;
  112. } TREEITEMSEARCH;
  113. typedef struct _SAVEVIEWDATA
  114. {
  115. TVITEMEXW item;
  116. WCHAR buffer[SAVEVIEW_BUFFER_MAX];
  117. WCHAR mlview[ML_VIEW_MAX];
  118. C_Config *pConfig;
  119. INT counter_root;
  120. INT counter_write;
  121. }SAVEVIEWDATA;
  122. typedef struct _NAVENUMSTRUCT
  123. {
  124. TVITEMW item;
  125. NAVENUMPROC_I callback;
  126. LPARAM lParam;
  127. HNAVCTRL hNav;
  128. } NAVENUMSTRUCT;
  129. typedef BOOL (CALLBACK *TREEITEMCB)(HWND, HTREEITEM, LPVOID);
  130. #define ABS(x) (((x) > 0) ? (x) : (-x))
  131. #define NAVSTYLE_DEFAULT 0x0000
  132. #define NAVSTYLE_MOUSEDOWNSELECT 0x0001
  133. #define NAVSTYLE_FOCUSED 0x0002
  134. #define NAVSTYLE_EDITMODE 0x0004
  135. // helpers
  136. static BOOL GetItemColors(HNAVCTRL hNav, UINT itemState, COLORREF *rgbBk, COLORREF *rgbFg)
  137. {
  138. INT rgbBkIndex, rgbFgIndex;
  139. switch(itemState)
  140. {
  141. case (NIS_SELECTED_I | NIS_FOCUSED_I): rgbBkIndex = WADLG_SELBAR_BGCOLOR; rgbFgIndex = WADLG_SELBAR_FGCOLOR; break;
  142. case NIS_SELECTED_I: rgbBkIndex = WADLG_INACT_SELBAR_BGCOLOR; rgbFgIndex = WADLG_INACT_SELBAR_FGCOLOR; break;
  143. case NIS_DROPHILITED_I: rgbBkIndex = WADLG_INACT_SELBAR_BGCOLOR; rgbFgIndex = WADLG_INACT_SELBAR_FGCOLOR; break;
  144. default: rgbBkIndex = WADLG_ITEMBG; rgbFgIndex = WADLG_ITEMFG; break;
  145. }
  146. if (rgbBk) *rgbBk = WADlg_getColor(rgbBkIndex);
  147. if (rgbFg) *rgbFg = WADlg_getColor(rgbFgIndex);
  148. return TRUE;
  149. }
  150. static BOOL EnumerateTreeItems(HWND hwndTree, HTREEITEM hStart, TREEITEMCB pfnItemCallback, LPVOID user)
  151. {
  152. HTREEITEM hChild;
  153. if (!pfnItemCallback) return FALSE;
  154. if (NULL == hStart || TVI_ROOT == hStart)
  155. hStart = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_ROOT, (LPARAM)0);
  156. while(NULL != hStart)
  157. {
  158. if (!pfnItemCallback(hwndTree, hStart, user))
  159. return FALSE;
  160. hChild = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_CHILD, (LPARAM)hStart);
  161. if (NULL != hChild)
  162. {
  163. if (!EnumerateTreeItems(hwndTree, hChild, pfnItemCallback, user))
  164. return FALSE;
  165. }
  166. hStart = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_NEXT, (LPARAM)hStart);
  167. }
  168. return TRUE;
  169. }
  170. static BOOL CALLBACK FindTreeItemByIdCB(HWND hwndTree, HTREEITEM hItem, LPVOID user)
  171. {
  172. if (!user) return FALSE;
  173. ((TREEITEMSEARCH*)user)->item.hItem = hItem;
  174. if ((BOOL)SendMessageW(hwndTree, TVM_GETITEMW, (WPARAM)0, (LPARAM)&((TREEITEMSEARCH*)user)->item))
  175. {
  176. if (((TREEITEMSEARCH*)user)->item.lParam &&
  177. (INT)((TREEITEMSEARCH*)user)->itemData == ((NAVITM*)((TREEITEMSEARCH*)user)->item.lParam)->id)
  178. {
  179. ((TREEITEMSEARCH*)user)->fFound = TRUE;
  180. return FALSE;
  181. }
  182. }
  183. return TRUE;
  184. }
  185. static INT CompareItemName(LCID Locale, UINT compFlags, LPCWSTR pszString, INT cchLength, HNAVITEM hItem)
  186. {
  187. INT result;
  188. if (!hItem || !pszString) return 0; // error
  189. if (NICF_INVARIANT_I & compFlags)
  190. {
  191. result = (((NAVITM*)hItem)->pszInvariant) ?
  192. CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, ((NAVITM*)hItem)->pszInvariant, -1, pszString, cchLength) :
  193. CSTR_LESS_THAN;
  194. if (CSTR_EQUAL == result) return CSTR_EQUAL;
  195. }
  196. if (NICF_DISPLAY_I & compFlags || 0 == (compFlags & ~NICF_IGNORECASE_I))
  197. {
  198. result = (((NAVITM*)hItem)->pszText) ?
  199. CompareStringW(Locale, (NICF_IGNORECASE_I & compFlags) ? NORM_IGNORECASE : 0, ((NAVITM*)hItem)->pszText, -1, pszString, cchLength) :
  200. CSTR_LESS_THAN;
  201. }
  202. return result;
  203. }
  204. static BOOL CALLBACK FindTreeItemByNameCB(HWND hwndTree, HTREEITEM hItem, LPVOID user)
  205. {
  206. if (!user) return FALSE;
  207. ((TREEITEMSEARCH*)user)->item.hItem = hItem;
  208. if ((BOOL)SendMessageW(hwndTree, TVM_GETITEMW, (WPARAM)0, (LPARAM)&((TREEITEMSEARCH*)user)->item))
  209. {
  210. if (CSTR_EQUAL == CompareItemName(((TREEITEMSEARCH*)user)->item.state, ((TREEITEMSEARCH*)user)->flags,
  211. (LPCWSTR)((TREEITEMSEARCH*)user)->itemData, ((TREEITEMSEARCH*)user)->item.cchTextMax,
  212. (NAVITM*)((TREEITEMSEARCH*)user)->item.lParam))
  213. {
  214. ((TREEITEMSEARCH*)user)->fFound = TRUE;
  215. return FALSE;
  216. }
  217. }
  218. return TRUE;
  219. }
  220. static BOOL CALLBACK ItemSizedCB(HWND hwndTree, HTREEITEM hItem, LPVOID user)
  221. {
  222. ((TVITEMW*)user)->hItem = hItem;
  223. if (!SendMessageW(hwndTree, TVM_GETITEMW, (WPARAM)0, (LPARAM)user)) return FALSE;
  224. if (((TVITEMW*)user)->lParam)
  225. {
  226. if (NIS_CUSTOMDRAW_I & ((NAVITM*)((TVITEMW*)user)->lParam)->style)
  227. {
  228. *(HTREEITEM*)((TVITEMW*)user)->pszText = hItem;
  229. if (SendMessageW(hwndTree, TVM_GETITEMRECT, FALSE, (LPARAM)((TVITEMW*)user)->pszText))
  230. {
  231. InvalidateRect(hwndTree, (RECT*)((TVITEMW*)user)->pszText, TRUE);
  232. }
  233. }
  234. }
  235. return TRUE;
  236. }
  237. static HNAVITEM FindNavItemByNavIdEx(HWND hwndTree, INT itemId, HTREEITEM hStart)
  238. {
  239. TREEITEMSEARCH search;
  240. search.fFound = FALSE;
  241. search.itemData = (INT_PTR)itemId;
  242. search.item.mask = TVIF_PARAM;
  243. search.flags = 0;
  244. EnumerateTreeItems(hwndTree, hStart, FindTreeItemByIdCB, &search);
  245. return (search.fFound) ? (HNAVITEM)search.item.lParam : NULL;
  246. }
  247. static INT GetNextFreeItemId(HNAVCTRL hNav)
  248. {
  249. if (!hNav) return 0;
  250. while (FindNavItemByNavIdEx(((NAVMNGR*)hNav)->hwndHost, ++((NAVMNGR*)hNav)->lastUsedId, TVI_ROOT));
  251. return ((NAVMNGR*)hNav)->lastUsedId;
  252. }
  253. static INT GetRealImageIndex(HNAVCTRL hNav, HNAVITEM hItem, INT imageType, COLORREF rgbBk, COLORREF rgbFg)
  254. {
  255. INT mlilIndex;
  256. if (!hNav) return -1;
  257. mlilIndex = NavItemI_GetImageIndex(hItem, imageType);
  258. if (-1 == mlilIndex )
  259. {
  260. if (((NAVMNGR*)hNav)->fnOnItemGetImageIndex) mlilIndex = ((NAVMNGR*)hNav)->fnOnItemGetImageIndex(hNav, hItem, imageType);
  261. if (-1 == mlilIndex) return -1;
  262. }
  263. return MLImageListI_GetRealIndex(((NAVMNGR*)hNav)->hmlilImages, mlilIndex, rgbBk, rgbFg);
  264. }
  265. static BOOL CALLBACK EnumNavItemCB(HWND hwndTree, HTREEITEM hItem, LPVOID user)
  266. {
  267. NAVENUMSTRUCT *pData;
  268. if (!user) return FALSE;
  269. pData = (NAVENUMSTRUCT*)user;
  270. pData->item.hItem = hItem;
  271. return (BOOL)SendMessageW(hwndTree, TVM_GETITEMW, (WPARAM)0, (LPARAM)&(pData->item)) ?
  272. pData->callback((HNAVITEM)pData->item.lParam, pData->lParam) : TRUE;
  273. }
  274. static BOOL CALLBACK SaveNavigationCB(HWND hwndTree, HTREEITEM hItem, LPVOID user)
  275. {
  276. if (!user) return FALSE; // very bad
  277. ((SAVEVIEWDATA*)user)->item.hItem = hItem;
  278. if ((BOOL)SendMessageW(hwndTree, TVM_GETITEMW, (WPARAM)0, (LPARAM)&((SAVEVIEWDATA*)user)->item))
  279. {
  280. INT order;
  281. BOOL bCollapsed = (SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_CHILD, (LPARAM)hItem) && !(TVIS_EXPANDED & ((SAVEVIEWDATA*)user)->item.state));
  282. if (!SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_PARENT, (LPARAM)hItem))
  283. {
  284. order = ++((SAVEVIEWDATA*)user)->counter_root;
  285. }
  286. else order = -1;
  287. if (order != -1 || bCollapsed || (TVIS_SELECTED & ((SAVEVIEWDATA*)user)->item.state))
  288. {
  289. INT remain = NavItemI_GetFullName((HNAVITEM)((SAVEVIEWDATA*)user)->item.lParam, ((SAVEVIEWDATA*)user)->buffer, SAVEVIEW_BUFFER_MAX);
  290. if (remain)
  291. {
  292. if ((order != -1 || bCollapsed) && remain < (SAVEVIEW_BUFFER_MAX - 8) )
  293. {
  294. if (S_OK == StringCchPrintfW(((SAVEVIEWDATA*)user)->buffer + remain, SAVEVIEW_BUFFER_MAX - remain, L",%d,%d", bCollapsed, order) &&
  295. S_OK == StringCchPrintfW(((SAVEVIEWDATA*)user)->mlview, ML_VIEW_MAX, MLV_PREFIX_A L"%02d", (((SAVEVIEWDATA*)user)->counter_write + 1)))
  296. {
  297. ((SAVEVIEWDATA*)user)->pConfig->WriteString(((SAVEVIEWDATA*)user)->mlview, ((SAVEVIEWDATA*)user)->buffer);
  298. ((SAVEVIEWDATA*)user)->counter_write++;
  299. }
  300. }
  301. }
  302. }
  303. }
  304. return TRUE;
  305. }
  306. static HNAVITEM GetNavItemFromTreeItem(HNAVCTRL hNav, HTREEITEM hTreeItem)
  307. {
  308. TVITEMW item;
  309. item.mask = TVIF_PARAM;
  310. item.hItem = hTreeItem;
  311. if (!hNav) return NULL;
  312. if (!SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETITEMW, (WPARAM)0, (LPARAM)&item)) return NULL;
  313. return (HNAVITEM)item.lParam;
  314. }
  315. static HNAVITEM NavItemI_GetNextEx(HNAVITEM hItem, UINT flag) // use TVGN_ as flags
  316. {
  317. TVITEMW treeItem;
  318. if (!hItem) return NULL;
  319. treeItem.hItem = (HTREEITEM)SendMessageW(((NAVITM*)hItem)->hwndTree, TVM_GETNEXTITEM, (WPARAM)flag, (LPARAM)((NAVITM*)hItem)->hTreeItem);
  320. if (!treeItem.hItem) return NULL;
  321. treeItem.mask = TVIF_PARAM;
  322. return (SendMessageW(((NAVITM*)hItem)->hwndTree, TVM_GETITEMW, (WPARAM)0, (LPARAM)&treeItem)) ? (HNAVITEM)treeItem.lParam : NULL;
  323. }
  324. static void PerformCustomHitTest(HNAVCTRL hNav, POINT pt, UINT *pHitFlags, HNAVITEM *phItem) // returns nav hit test result
  325. {
  326. UINT flags, test;
  327. flags = 0;
  328. test = (pHitFlags) ? *pHitFlags : 1;
  329. if (TVHT_NOWHERE & test) flags |= NAVHT_NOWHERE_I;
  330. if (TVHT_ONITEMLABEL & test) flags |= NAVHT_ONITEM_I;
  331. if (TVHT_ONITEMINDENT & test) flags |= NAVHT_ONITEMINDENT_I;
  332. if (TVHT_ONITEMRIGHT & test) flags |= NAVHT_ONITEMRIGHT_I;
  333. if (TVHT_ABOVE & test) flags |= NAVHT_ABOVE_I;
  334. if (TVHT_BELOW & test) flags |= NAVHT_BELOW_I;
  335. if (TVHT_TORIGHT & test) flags |= NAVHT_TORIGHT_I;
  336. if (TVHT_TOLEFT & test) flags |= NAVHT_TOLEFT_I;
  337. if (pHitFlags) *pHitFlags = flags;
  338. if (hNav && phItem && *phItem && pHitFlags)
  339. {
  340. if (TVHT_ONITEMICON & test) *pHitFlags |= (SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETNEXTITEM,
  341. (WPARAM)TVGN_CHILD, (LPARAM)((NAVITM*)(*phItem))->hTreeItem)) ?
  342. NAVHT_ONITEMBUTTON_I : NAVHT_ONITEM_I;
  343. if ((NIS_WANTHITTEST_I & ((NAVITM*)(*phItem))->style) && ((NAVMNGR*)hNav)->fnOnHitTest)
  344. {
  345. ((NAVMNGR*)hNav)->fnOnHitTest(hNav, pt, pHitFlags, phItem, ((NAVITM*)(*phItem))->lParam);
  346. }
  347. }
  348. }
  349. static HTREEITEM TreeItemFromCursor(HNAVCTRL hNav, HTREEITEM *phtiWantExpand)
  350. {
  351. HTREEITEM hTreeItem;
  352. TVHITTESTINFO hit;
  353. if (phtiWantExpand) *phtiWantExpand = NULL;
  354. if(!GetCursorPos(&hit.pt)) return NULL;
  355. MapWindowPoints(HWND_DESKTOP, ((NAVMNGR*)hNav)->hwndHost, &hit.pt, 1);
  356. hTreeItem = (HTREEITEM)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_HITTEST, (WPARAM)0, (LPARAM)&hit);
  357. if (0 == (TVHT_ONITEM & hit.flags))
  358. {
  359. if ((TVHT_ONITEMRIGHT | TVHT_ONITEMINDENT) & hit.flags)
  360. {
  361. if (0 == (TVS_FULLROWSELECT & GetWindowLongPtrW(((NAVMNGR*)hNav)->hwndHost, GWL_STYLE))) hTreeItem = NULL;
  362. }
  363. }
  364. if(hTreeItem)
  365. {
  366. HNAVITEM hItem;
  367. hItem = GetNavItemFromTreeItem(hNav, hTreeItem);
  368. PerformCustomHitTest(hNav, hit.pt, &hit.flags, &hItem);
  369. hTreeItem = (hItem) ? ((NAVITM*)hItem)->hTreeItem : NULL;
  370. if (NAVHT_ONITEMBUTTON_I & hit.flags)
  371. {
  372. if (phtiWantExpand) *phtiWantExpand = hTreeItem;
  373. hTreeItem = NULL;
  374. }
  375. }
  376. return hTreeItem;
  377. }
  378. static NAVITEMSTATEREC *NavCtrlI_FindItemStateRec(HNAVCTRL hNav, HNAVITEM hItem, BOOL fClearOnSuccess)
  379. {
  380. wchar_t name[1024] = {0};
  381. if (!hNav || !hItem) return NULL;
  382. if (NavItemI_GetFullName(hItem, name, 1024))
  383. {
  384. for (INT idx = 0; idx < ((NAVMNGR*)hNav)->statesCount; idx++)
  385. {
  386. if (((NAVMNGR*)hNav)->pStates[idx].pszFullName &&
  387. CSTR_EQUAL == CompareStringW(LOCALE_USER_DEFAULT, 0, name, -1,
  388. ((NAVMNGR*)hNav)->pStates[idx].pszFullName, -1))
  389. {
  390. if (fClearOnSuccess)
  391. {
  392. free(((NAVMNGR*)hNav)->pStates[idx].pszFullName);
  393. ((NAVMNGR*)hNav)->pStates[idx].pszFullName = NULL;
  394. }
  395. return &((NAVMNGR*)hNav)->pStates[idx];
  396. }
  397. }
  398. }
  399. return NULL;
  400. }
  401. static LRESULT EditCtrlWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  402. {
  403. SCEDIT *pEdit;
  404. pEdit = (SCEDIT*)GetPropW(hwnd, WNDPROP_SCCTRLW);
  405. if (!pEdit) return (IsWindowUnicode(hwnd)) ? DefWindowProcW(hwnd, uMsg, wParam, lParam) : DefWindowProcA(hwnd, uMsg, wParam, lParam);
  406. switch(uMsg)
  407. {
  408. case WM_NCDESTROY: // detach
  409. RemovePropW(hwnd, WNDPROP_SCCTRLW);
  410. if (pEdit->fUnicode)
  411. {
  412. CallWindowProcW(pEdit->fnOldProc, hwnd, uMsg, wParam, lParam);
  413. SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)pEdit->fnOldProc);
  414. }
  415. else
  416. {
  417. CallWindowProcA(pEdit->fnOldProc, hwnd, uMsg, wParam, lParam);
  418. SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)pEdit->fnOldProc);
  419. }
  420. free(pEdit);
  421. return 0;
  422. case WM_ERASEBKGND: return 1;
  423. case WM_NCPAINT:
  424. {
  425. HDC hdc;
  426. hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_WINDOW | DCX_INTERSECTUPDATE | DCX_CLIPSIBLINGS);
  427. if (hdc)
  428. {
  429. RECT rc;
  430. GetClientRect(hwnd, &rc);
  431. FrameRect(hdc, &rc, (HBRUSH)MlStockObjects_Get(ITEMTEXT_BRUSH));
  432. ReleaseDC(hwnd, hdc);
  433. }
  434. return 0;
  435. }
  436. break;
  437. case WM_PAINT:
  438. {
  439. RECT rc, rv;
  440. GetClientRect(hwnd, &rc);
  441. SetRect(&rv, 0, 0, rc.right, 1);
  442. ValidateRect(hwnd, &rv);
  443. SetRect(&rv, 0, rc.bottom - 1, rc.right, rc.bottom);
  444. ValidateRect(hwnd, &rv);
  445. SetRect(&rv, 0, 1, 1, rc.bottom);
  446. ValidateRect(hwnd, &rv);
  447. SetRect(&rv, rc.right-1, 1, rc.right, rc.bottom);
  448. ValidateRect(hwnd, &rv);
  449. break;
  450. }
  451. case WM_GETDLGCODE:
  452. switch(wParam)
  453. {
  454. case VK_RETURN:
  455. SendMessageW(GetParent(hwnd), TVM_ENDEDITLABELNOW, FALSE, 0L); return 0; // tell trew-view that we done and return 0
  456. case VK_ESCAPE:
  457. SendMessageW(GetParent(hwnd), TVM_ENDEDITLABELNOW, TRUE, 0L); return 0; // tell trew-view that we done and return 0
  458. }
  459. break;
  460. case WM_SETCURSOR:
  461. if (HTCLIENT == LOWORD(lParam))
  462. {
  463. SetCursor(LoadCursor(NULL, IDC_IBEAM));
  464. return 0;
  465. }
  466. break;
  467. }
  468. return (pEdit->fUnicode) ? CallWindowProcW(pEdit->fnOldProc, hwnd, uMsg, wParam, lParam) :
  469. CallWindowProcA(pEdit->fnOldProc, hwnd, uMsg, wParam, lParam);
  470. }
  471. static LRESULT TreeViewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  472. {
  473. SCTREE *pTree;
  474. pTree = (SCTREE*)GetPropW(hwnd, WNDPROP_SCCTRLW);
  475. if (!pTree)
  476. return (IsWindowUnicode(hwnd)) ? DefWindowProcW(hwnd, uMsg, wParam, lParam) : DefWindowProcA(hwnd, uMsg, wParam, lParam);
  477. switch(uMsg)
  478. {
  479. case WM_NCDESTROY: // detach
  480. RemovePropW(hwnd, WNDPROP_SCCTRLW);
  481. if (pTree->fUnicode)
  482. {
  483. CallWindowProcW(pTree->fnOldProc, hwnd, uMsg, wParam, lParam);
  484. SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)pTree->fnOldProc);
  485. }
  486. else
  487. {
  488. CallWindowProcA(pTree->fnOldProc, hwnd, uMsg, wParam, lParam);
  489. SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)pTree->fnOldProc);
  490. }
  491. free(pTree);
  492. return 0;
  493. case WM_ERASEBKGND:
  494. if (wParam && (TVS_FULLROWSELECT & GetWindowLongPtrW(hwnd, GWL_STYLE)))
  495. {
  496. RECT rc;
  497. HTREEITEM hItem;
  498. GetClientRect(hwnd, &rc);
  499. hItem = (HTREEITEM)SendMessageW(hwnd, TVM_GETNEXTITEM, TVGN_LASTVISIBLE, 0L);
  500. if (hItem)
  501. {
  502. RECT ri;
  503. *(HTREEITEM*)&ri = hItem;
  504. if (SendMessageW(hwnd, TVM_GETITEMRECT, FALSE, (LPARAM)&ri)) rc.top = ri.bottom;
  505. }
  506. if (rc.top < rc.bottom)
  507. {
  508. SetBkColor((HDC)wParam, WADlg_getColor(WADLG_ITEMBG));
  509. ExtTextOutW((HDC)wParam, 0, 0, ETO_OPAQUE, &rc, L"", 0, 0);
  510. }
  511. return 1;
  512. }
  513. return 0;
  514. case WM_LBUTTONDOWN:
  515. case WM_RBUTTONDOWN:
  516. {
  517. TVHITTESTINFO hit;
  518. HNAVITEM hItem;
  519. NAVMNGR *pMngr;
  520. hit.pt.x = GET_X_LPARAM(lParam);
  521. hit.pt.y = GET_Y_LPARAM(lParam);
  522. SendMessageW(hwnd, TVM_HITTEST, (WPARAM)0, (LPARAM)&hit);
  523. pMngr = (NAVMNGR*)GetPropW(hwnd, NAVMGR_HWNDPROPW);
  524. if (hit.hItem)
  525. {
  526. hItem = GetNavItemFromTreeItem(pMngr, hit.hItem);
  527. PerformCustomHitTest(pMngr, hit.pt, &hit.flags, &hItem);
  528. if (hItem && pMngr && (NAVSTYLE_MOUSEDOWNSELECT & pMngr->style))
  529. {
  530. SendMessageW(hwnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM)((NAVITM*)hItem)->hTreeItem);
  531. }
  532. }
  533. else
  534. hItem = NULL;
  535. if (!hItem)
  536. {
  537. SendMessageW(hwnd, TVM_ENDEDITLABELNOW, (WPARAM)TRUE, 0L);
  538. return 0;
  539. }
  540. else
  541. {
  542. HWND hEdit = FindWindowExW(hwnd, NULL, L"Edit", NULL);
  543. if (NULL != hEdit && IsWindowVisible(hEdit))
  544. {
  545. PostMessageW(hwnd, uMsg, wParam, lParam);
  546. }
  547. else
  548. {
  549. pTree->supressEdit = FALSE;
  550. if (0 != pTree->focused)
  551. {
  552. DWORD clicked = GetTickCount();
  553. if (clicked >= pTree->focused && (clicked - pTree->focused) < 200)
  554. pTree->supressEdit = TRUE;
  555. pTree->focused = 0;
  556. }
  557. }
  558. }
  559. }
  560. break;
  561. case WM_LBUTTONDBLCLK:
  562. if (TVS_FULLROWSELECT == (TVS_FULLROWSELECT & (UINT)GetWindowLongPtrW(hwnd, GWL_STYLE)))
  563. {
  564. TVHITTESTINFO test;
  565. test.pt.x = GET_X_LPARAM(lParam);
  566. test.pt.y = GET_Y_LPARAM(lParam);
  567. if(SendMessageW(hwnd, TVM_HITTEST, 0, (LPARAM)&test) && (TVHT_ONITEMRIGHT & test.flags))
  568. {
  569. HWND hParent;
  570. NMHDR hdr;
  571. hdr.code = NM_DBLCLK;
  572. hdr.hwndFrom = hwnd;
  573. hdr.idFrom = GetDlgCtrlID(hwnd);
  574. hParent = GetParent(hwnd);
  575. if (hParent) SendMessageW(hParent, WM_NOTIFY, hdr.idFrom, (LPARAM)&hdr);
  576. return 0;
  577. }
  578. }
  579. break;
  580. case WM_CTLCOLOREDIT:
  581. SetTextColor((HDC)wParam, WADlg_getColor(WADLG_ITEMFG));
  582. SetBkColor((HDC)wParam, WADlg_getColor(WADLG_ITEMBG));
  583. return (LRESULT)MlStockObjects_Get(ITEMBCK_BRUSH);
  584. case WM_SIZE:
  585. {
  586. TVITEMW item;
  587. RECT ri;
  588. item.mask = TVIF_PARAM;
  589. item.pszText = (LPWSTR)&ri;
  590. EnumerateTreeItems(hwnd, NULL, ItemSizedCB, &item);
  591. }
  592. break;
  593. case WM_CHAR:
  594. pTree->supressEdit = FALSE;
  595. return (VK_RETURN == wParam) ? 0 :
  596. ((pTree->fUnicode) ? CallWindowProcW(pTree->fnOldProc, hwnd, uMsg, wParam, lParam) :
  597. CallWindowProcA(pTree->fnOldProc, hwnd, uMsg, wParam, lParam));
  598. case WM_GETDLGCODE:
  599. {
  600. LRESULT r = (pTree->fUnicode) ? CallWindowProcW(pTree->fnOldProc, hwnd, uMsg, wParam, lParam) :
  601. CallWindowProcA(pTree->fnOldProc, hwnd, uMsg, wParam, lParam);
  602. if (lParam)
  603. {
  604. MSG *pMsg = (LPMSG)lParam;
  605. if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_KEYUP)
  606. {
  607. switch(pMsg->wParam)
  608. {
  609. case VK_RETURN: r |= DLGC_WANTMESSAGE; break;
  610. case VK_TAB:
  611. case VK_ESCAPE: SendMessageW(hwnd, TVM_ENDEDITLABELNOW, TRUE, 0L); break;
  612. }
  613. }
  614. }
  615. return r;
  616. }
  617. case WM_SETFOCUS:
  618. pTree->focused = GetTickCount();
  619. break;
  620. case WM_TIMER:
  621. if (42 == wParam && FALSE != pTree->supressEdit)
  622. {
  623. KillTimer(hwnd, wParam);
  624. pTree->supressEdit = FALSE;
  625. return 0;
  626. }
  627. break;
  628. }
  629. return (pTree->fUnicode) ? CallWindowProcW(pTree->fnOldProc, hwnd, uMsg, wParam, lParam) :
  630. CallWindowProcA(pTree->fnOldProc, hwnd, uMsg, wParam, lParam);
  631. }
  632. static BOOL SubclassEditControl(HWND hwndEdit)
  633. {
  634. if (!hwndEdit || !IsWindow(hwndEdit)) return FALSE;
  635. SCEDIT *pEdit = (SCEDIT*)calloc(1, sizeof(SCEDIT));
  636. if (!pEdit) return FALSE;
  637. pEdit->fUnicode = IsWindowUnicode(hwndEdit);
  638. pEdit->fnOldProc = (WNDPROC)(LONG_PTR)((pEdit->fUnicode) ? SetWindowLongPtrW(hwndEdit, GWLP_WNDPROC, (LONGX86)(LONG_PTR)EditCtrlWndProc) :
  639. SetWindowLongPtrA(hwndEdit, GWLP_WNDPROC, (LONGX86)(LONG_PTR)EditCtrlWndProc));
  640. if (!pEdit->fnOldProc || !SetPropW(hwndEdit, WNDPROP_SCCTRLW, pEdit))
  641. {
  642. if (pEdit->fnOldProc)
  643. {
  644. if (pEdit->fUnicode) SetWindowLongPtrW(hwndEdit, GWLP_WNDPROC, (LONGX86)(LONG_PTR)pEdit->fnOldProc);
  645. else SetWindowLongPtrA(hwndEdit, GWLP_WNDPROC, (LONGX86)(LONG_PTR)pEdit->fnOldProc);
  646. }
  647. free(pEdit);
  648. return FALSE;
  649. }
  650. return TRUE;
  651. }
  652. static BOOL SubclassTreeView(HWND hwndTree)
  653. {
  654. if (!hwndTree || !IsWindow(hwndTree)) return FALSE;
  655. SCTREE *pTree = (SCTREE*)calloc(1, sizeof(SCTREE));
  656. if (!pTree) return FALSE;
  657. pTree->fUnicode = IsWindowUnicode(hwndTree);
  658. pTree->fnOldProc = (WNDPROC)(LONG_PTR)((pTree->fUnicode) ? SetWindowLongPtrW(hwndTree, GWLP_WNDPROC, (LONGX86)(LONG_PTR)TreeViewWndProc) :
  659. SetWindowLongPtrA(hwndTree, GWLP_WNDPROC, (LONGX86)(LONG_PTR)TreeViewWndProc));
  660. if (!pTree->fnOldProc || !SetPropW(hwndTree, WNDPROP_SCCTRLW, pTree))
  661. {
  662. if (pTree->fnOldProc)
  663. {
  664. if (pTree->fUnicode) SetWindowLongPtrW(hwndTree, GWLP_WNDPROC, (LONGX86)(LONG_PTR)pTree->fnOldProc);
  665. else SetWindowLongPtrA(hwndTree, GWLP_WNDPROC, (LONGX86)(LONG_PTR)pTree->fnOldProc);
  666. }
  667. free(pTree);
  668. return FALSE;
  669. }
  670. return TRUE;
  671. }
  672. static BOOL NavCtrlI_SaveStates(HNAVCTRL hNav)
  673. {
  674. BOOL result;
  675. SAVEVIEWDATA save;
  676. if (!hNav || !((NAVMNGR*)hNav)->pConfig) return FALSE;
  677. save.item.mask = TVIF_STATE | TVIF_PARAM;
  678. save.item.stateMask = TVIS_EXPANDED | TVIS_SELECTED;
  679. save.pConfig = ((NAVMNGR*)hNav)->pConfig;
  680. save.counter_root = 0;
  681. save.counter_write = 0;
  682. result = EnumerateTreeItems(((NAVMNGR*)hNav)->hwndHost, TVI_ROOT, SaveNavigationCB, &save);
  683. if (!result) save.counter_write = 0;
  684. ((NAVMNGR*)hNav)->pConfig->WriteInt(MLV_PREFIX_A L"count", save.counter_write);
  685. return result;
  686. }
  687. static BOOL NavCtrlI_DeleteStates(HNAVCTRL hNav)
  688. {
  689. if (!hNav) return FALSE;
  690. if (((NAVMNGR*)hNav)->pStates)
  691. {
  692. INT i;
  693. for (i =0; i < ((NAVMNGR*)hNav)->statesCount; i++)
  694. {
  695. if (((NAVMNGR*)hNav)->pStates[i].pszFullName) free(((NAVMNGR*)hNav)->pStates[i].pszFullName);
  696. }
  697. free(((NAVMNGR*)hNav)->pStates);
  698. ((NAVMNGR*)hNav)->pStates = NULL;
  699. }
  700. ((NAVMNGR*)hNav)->statesCount = 0;
  701. return TRUE;
  702. }
  703. static BOOL NavCtrlI_LoadStates(HNAVCTRL hNav)
  704. {
  705. INT index, count, len;
  706. wchar_t mlview[ML_VIEW_MAX] = {0};
  707. const wchar_t *data;
  708. if (!hNav || !((NAVMNGR*)hNav)->pConfig) return FALSE;
  709. if (!NavCtrlI_DeleteStates(hNav)) return FALSE;
  710. count = ((NAVMNGR*)hNav)->pConfig->ReadInt(MLV_PREFIX_A L"count", 0);
  711. if (count < 1) return TRUE;
  712. ((NAVMNGR*)hNav)->pStates = (NAVITEMSTATEREC*)calloc(count, sizeof(NAVITEMSTATEREC));
  713. if (!((NAVMNGR*)hNav)->pStates) return FALSE;
  714. for (index = 0; index < count; index++)
  715. {
  716. StringCchPrintfW(mlview, ML_VIEW_MAX, MLV_PREFIX_A L"%02d", index + 1);
  717. //AutoWide aw(((NAVMNGR*)hNav)->pConfig->ReadString(mlview, ""), CP_UTF8);
  718. data = ((NAVMNGR*)hNav)->pConfig->ReadString(mlview, L"");//(LPCWSTR)aw;
  719. if (data && *data)
  720. {
  721. len = lstrlenW(data);
  722. if (len > 4 && len < 4096)
  723. {
  724. while (len > 0 && data[len-1] != L',') len--;
  725. if (len)
  726. {
  727. ((NAVMNGR*)hNav)->pStates[index].nOrder = _wtoi(&data[len]);
  728. len--;
  729. while (len > 0 && data[len-1] != L',')len--;
  730. if (len) ((NAVMNGR*)hNav)->pStates[index].fCollapsed = ( 0 != _wtoi(&data[len]));
  731. if (len > 1)
  732. {
  733. ((NAVMNGR*)hNav)->pStates[index].pszFullName = (LPWSTR)calloc(len, sizeof(wchar_t));
  734. if (!((NAVMNGR*)hNav)->pStates[index].pszFullName) continue;
  735. if (S_OK == StringCchCopyNW(((NAVMNGR*)hNav)->pStates[index].pszFullName, len, data, len -1))
  736. {
  737. ((NAVMNGR*)hNav)->statesCount++;
  738. }
  739. }
  740. }
  741. }
  742. }
  743. }
  744. ((NAVMNGR*)hNav)->lastOrderIndex = ((NAVMNGR*)hNav)->statesCount;
  745. return (count == ((NAVMNGR*)hNav)->statesCount);
  746. }
  747. static BOOL OnNavTree_Click(HNAVCTRL hNav, INT actionId, LRESULT *pResult)
  748. {
  749. if (hNav && ((NAVMNGR*)hNav)->fnOnItemClick)
  750. {
  751. HTREEITEM hTreeItem, hTreeExpand = 0;
  752. if (ACTION_ENTER_I == actionId)
  753. {
  754. hTreeExpand = hTreeItem = (HTREEITEM)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETNEXTITEM, (WPARAM)TVGN_CARET, (LPARAM)0L);
  755. }
  756. else
  757. {
  758. hTreeItem = TreeItemFromCursor(hNav, &hTreeExpand);
  759. }
  760. if (hTreeExpand || ((ACTION_DBLCLICKL_I == actionId) && hTreeItem && !hTreeExpand))
  761. {
  762. if (ACTION_CLICKL_I == actionId || (ACTION_DBLCLICKL_I == actionId && hTreeItem && !hTreeExpand))
  763. {
  764. if (ACTION_DBLCLICKL_I == actionId) hTreeExpand = hTreeItem;
  765. hTreeItem = (HTREEITEM)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETNEXTITEM, (WPARAM)TVGN_CARET, (LPARAM)0L);
  766. while (hTreeItem)
  767. {
  768. hTreeItem = (HTREEITEM)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETNEXTITEM, (WPARAM)TVGN_PARENT, (LPARAM)hTreeItem);
  769. if (hTreeItem == hTreeExpand) break;
  770. }
  771. if (hTreeItem == hTreeExpand &&
  772. (TVIS_EXPANDED == (TVIS_EXPANDED & SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETITEMSTATE, (WPARAM)hTreeExpand, (LPARAM)TVIS_EXPANDED))))
  773. {
  774. SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_SELECTITEM, (WPARAM)TVGN_CARET, (LPARAM)hTreeExpand);
  775. }
  776. SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_EXPAND, (WPARAM)TVE_TOGGLE, (LPARAM)hTreeExpand);
  777. InvalidateRect(((NAVMNGR*)hNav)->hwndHost, NULL, TRUE);
  778. if (ACTION_DBLCLICKL_I == actionId)
  779. {
  780. HNAVITEM hItem;
  781. hItem = GetNavItemFromTreeItem(hNav, hTreeExpand);
  782. if (hItem) ((NAVMNGR*)hNav)->fnOnItemClick(hNav, hItem, actionId);
  783. }
  784. *pResult = TRUE;
  785. return (NULL == hTreeItem);
  786. }
  787. else if (ACTION_DBLCLICKL_I != actionId) hTreeItem = hTreeExpand;
  788. }
  789. if (hTreeItem)
  790. {
  791. HNAVITEM hItem;
  792. hItem = GetNavItemFromTreeItem(hNav, hTreeItem);
  793. if (hItem)
  794. {
  795. *pResult = ((NAVMNGR*)hNav)->fnOnItemClick(hNav, hItem, actionId);
  796. return (BOOL)*pResult;
  797. }
  798. return FALSE;
  799. }
  800. }
  801. return FALSE;
  802. }
  803. static BOOL OnTV_DeleteItem(HNAVCTRL hNav, TVITEMW *pItem)
  804. {
  805. if (pItem->lParam)
  806. {
  807. if (((NAVMNGR*)hNav)->fnOnItemDelete) ((NAVMNGR*)hNav)->fnOnItemDelete(hNav, (HNAVITEM)pItem->lParam);
  808. NavItemI_SetText((HNAVITEM)pItem->lParam, NULL);
  809. NavItemI_SetInvariantText((HNAVITEM)pItem->lParam, NULL);
  810. free((NAVITM*)pItem->lParam);
  811. }
  812. return FALSE;
  813. }
  814. static BOOL OnTV_CustomDraw(HNAVCTRL hNav, NMTVCUSTOMDRAW *cd, LRESULT *pResult)
  815. {
  816. NAVMNGR *manager;
  817. manager = (NAVMNGR*)hNav;
  818. *pResult = CDRF_DODEFAULT;
  819. switch (cd->nmcd.dwDrawStage)
  820. {
  821. case CDDS_PREPAINT:
  822. manager->drawStruct.hdc = cd->nmcd.hdc;
  823. manager->drawInternal = 0;
  824. if ((TVS_FULLROWSELECT & GetWindowLongPtrW(manager->hwndHost, GWL_STYLE))) manager->drawInternal |= 0x0001;
  825. if (0x8000 & GetAsyncKeyState( GetSystemMetrics(SM_SWAPBUTTON) ? VK_RBUTTON : VK_LBUTTON)) manager->drawInternal |= 0x0010;
  826. *pResult = CDRF_NOTIFYITEMDRAW;
  827. break;
  828. case CDDS_ITEMPREPAINT:
  829. manager->drawStruct.drawStage = NIDS_PREPAINT_I;
  830. manager->drawStruct.prc = &cd->nmcd.rc;
  831. manager->drawStruct.iLevel = cd->iLevel;
  832. if (CDIS_SELECTED & cd->nmcd.uItemState)
  833. {
  834. manager->drawStruct.itemState = NIS_SELECTED_I;
  835. if (0 != (CDIS_FOCUS & cd->nmcd.uItemState) ||
  836. 0 != (NAVSTYLE_FOCUSED & manager->style))
  837. {
  838. manager->drawStruct.itemState |= NIS_FOCUSED_I;
  839. }
  840. }
  841. else
  842. {
  843. HTREEITEM hTreeItem;
  844. manager->drawStruct.itemState = NIS_NORMAL_I;
  845. if (0x0010 & manager->drawInternal) TreeItemFromCursor(hNav, &hTreeItem);
  846. else hTreeItem = NULL;
  847. if (!hTreeItem)
  848. {
  849. UINT state;
  850. state = (UINT)SendMessageW(cd->nmcd.hdr.hwndFrom, TVM_GETITEMSTATE,
  851. (WPARAM)cd->nmcd.dwItemSpec, TVIS_DROPHILITED);
  852. if (TVIS_DROPHILITED & state)
  853. manager->drawStruct.itemState = NIS_DROPHILITED_I;
  854. }
  855. }
  856. GetItemColors(hNav, manager->drawStruct.itemState, &cd->clrTextBk, &cd->clrText);
  857. if (0 == (0x0001 & manager->drawInternal))
  858. {
  859. COLORREF rgbBk, rgbFg;
  860. GetItemColors(hNav, NIS_NORMAL_I, &rgbBk, &rgbFg);
  861. SetBkColor(cd->nmcd.hdc, rgbBk);
  862. SetTextColor(cd->nmcd.hdc, rgbFg);
  863. }
  864. else
  865. {
  866. SetBkColor(cd->nmcd.hdc, cd->clrTextBk);
  867. SetTextColor(cd->nmcd.hdc, cd->clrText);
  868. }
  869. if (cd->nmcd.lItemlParam)
  870. {
  871. NAVITM *pItem;
  872. pItem = ((NAVITM*)cd->nmcd.lItemlParam);
  873. if (pItem->hFont) manager->drawStruct.hFont = pItem->hFont;
  874. else if ((NIS_BOLD_I | NIS_ITALIC_I | NIS_UNDERLINE_I) & pItem->style)
  875. {
  876. LOGFONTW lf = { 0 };
  877. manager->drawStruct.hFont = (HFONT)::SendMessageW(cd->nmcd.hdr.hwndFrom, WM_GETFONT, 0, 0);
  878. GetObjectW(manager->drawStruct.hFont, sizeof(LOGFONTW), &lf);
  879. if (NIS_BOLD_I & pItem->style) lf.lfWeight = FW_BOLD;
  880. if (NIS_ITALIC_I & pItem->style) lf.lfItalic = TRUE;
  881. if (NIS_UNDERLINE_I & pItem->style) lf.lfUnderline = TRUE;
  882. manager->drawStruct.hFont = CreateFontIndirectW(&lf);
  883. }
  884. else manager->drawStruct.hFont = NULL;
  885. if (manager->drawStruct.hFont)
  886. {
  887. manager->hfontOld = (HFONT)SelectObject(cd->nmcd.hdc, manager->drawStruct.hFont);
  888. *pResult |= CDRF_NEWFONT;
  889. if (pItem->hFont != manager->drawStruct.hFont) *pResult |= CDRF_NOTIFYPOSTPAINT;
  890. }
  891. if((NIS_CUSTOMDRAW_I & pItem->style) && manager->fnOnCustomDraw)
  892. {
  893. INT result;
  894. manager->drawStruct.clrTextBk = cd->clrTextBk;
  895. manager->drawStruct.clrText = cd->clrText;
  896. result = manager->fnOnCustomDraw(hNav, pItem, &manager->drawStruct, pItem->lParam);
  897. if (NICDRF_SKIPDEFAULT_I & result)
  898. {
  899. SelectObject(cd->nmcd.hdc, manager->hfontOld);
  900. DeleteObject(manager->drawStruct.hFont);
  901. manager->drawStruct.hFont = NULL;
  902. *pResult |= CDRF_SKIPDEFAULT;
  903. }
  904. if (NICDRF_NEWFONT_I & result) *pResult |= CDRF_NEWFONT;
  905. if (NICDRF_NOTIFYPOSTPAINT_I & result)
  906. {
  907. pItem->style |= NIS_WANTPOSTPAINT_I;
  908. *pResult |= CDRF_NOTIFYPOSTPAINT;
  909. }
  910. else pItem->style &= ~NIS_WANTPOSTPAINT_I;
  911. }
  912. }
  913. break;
  914. case CDDS_ITEMPOSTPAINT:
  915. if(NIS_WANTPOSTPAINT_I & ((NAVITM*)cd->nmcd.lItemlParam)->style)
  916. {
  917. INT result;
  918. manager->drawStruct.drawStage = NIDS_POSTPAINT_I;
  919. result = manager->fnOnCustomDraw(hNav, (HNAVITEM)cd->nmcd.lItemlParam, &manager->drawStruct, ((NAVITM*)cd->nmcd.lItemlParam)->lParam);
  920. if (NICDRF_SKIPDEFAULT_I & result) *pResult |= CDRF_SKIPDEFAULT;
  921. }
  922. if (manager->drawStruct.hFont && manager->drawStruct.hFont != ((NAVITM*)cd->nmcd.lItemlParam)->hFont)
  923. {
  924. SelectObject(cd->nmcd.hdc, manager->hfontOld);
  925. DeleteObject(manager->drawStruct.hFont);
  926. manager->drawStruct.hFont = NULL;
  927. }
  928. break;
  929. }
  930. return TRUE;
  931. }
  932. static BOOL OnTV_GetDispInfo(HNAVCTRL hNav, NMTVDISPINFOW *di, LRESULT *pResult)
  933. {
  934. BOOL handled;
  935. NAVMNGR *manager;
  936. manager = (NAVMNGR*)hNav;
  937. handled = FALSE;
  938. if((TVIF_IMAGE | TVIF_SELECTEDIMAGE) & di->item.mask)
  939. {
  940. if (di->item.lParam)
  941. {
  942. INT itemState;
  943. COLORREF rgbBk, rgbFg;
  944. itemState = NIS_NORMAL_I;
  945. if (TVS_FULLROWSELECT == (TVS_FULLROWSELECT & (UINT)GetWindowLongPtrW(manager->hwndHost, GWL_STYLE)))
  946. {
  947. itemState = di->item.state;
  948. if (TVIS_DROPHILITED & di->item.state)
  949. {
  950. if (0x8000 & GetAsyncKeyState( GetSystemMetrics(SM_SWAPBUTTON) ? VK_RBUTTON : VK_LBUTTON))
  951. {
  952. HTREEITEM hTreeItem;
  953. TreeItemFromCursor(hNav, &hTreeItem);
  954. itemState = (hTreeItem) ? NIS_NORMAL_I : NIS_DROPHILITED_I;
  955. }
  956. else
  957. itemState = NIS_DROPHILITED_I;
  958. }
  959. else if (TVIS_SELECTED & di->item.state)
  960. {
  961. itemState = NIS_SELECTED_I;
  962. if (0 != ((NAVSTYLE_FOCUSED | NAVSTYLE_EDITMODE) & manager->style))
  963. itemState |= NIS_FOCUSED_I;
  964. }
  965. }
  966. GetItemColors(hNav, itemState, &rgbBk, &rgbFg);
  967. if (TVIF_IMAGE & di->item.mask)
  968. {
  969. di->item.iImage = GetRealImageIndex(hNav, (NAVITM*)di->item.lParam, IMAGE_NORMAL_I, rgbBk, rgbFg);
  970. }
  971. if (TVIF_SELECTEDIMAGE & di->item.mask)
  972. {
  973. di->item.iSelectedImage = ((TVIF_IMAGE & di->item.mask) &&
  974. ((NAVITM*)(di->item.lParam))->iImage == ((NAVITM*)(di->item.lParam))->iSelectedImage) ?
  975. di->item.iImage :
  976. GetRealImageIndex(hNav, (NAVITM*)di->item.lParam, IMAGE_SELECTED_I, rgbBk, rgbFg);
  977. }
  978. handled = TRUE;
  979. }
  980. }
  981. if (TVIF_CHILDREN & di->item.mask)
  982. {
  983. di->item.cChildren = (di->item.lParam) ? (NIS_HASCHILDREN_I & ((NAVITM*)di->item.lParam)->style) : 0;
  984. handled = TRUE;
  985. }
  986. if (TVIF_TEXT & di->item.mask)
  987. {
  988. di->item.pszText = (di->item.lParam) ?
  989. ((NAVITM*)di->item.lParam)->pszText : WASABI_API_LNGSTRINGW(IDS_BAD_ITEM);
  990. handled = TRUE;
  991. }
  992. return handled;
  993. }
  994. static BOOL OnTV_Click(HNAVCTRL hNav, NMHDR *pnmh, LRESULT *pResult)
  995. {
  996. return OnNavTree_Click(hNav, ACTION_CLICKL_I, pResult);
  997. }
  998. static BOOL OnTV_BeginDrag(HNAVCTRL hNav, NMTREEVIEWW *pnmtv)
  999. {
  1000. if (hNav && ((NAVMNGR*)hNav)->fnOnBeginDrag)
  1001. {
  1002. ((NAVMNGR*)hNav)->fnOnBeginDrag(hNav, (HNAVITEM)pnmtv->itemNew.lParam, pnmtv->ptDrag);
  1003. }
  1004. return FALSE;
  1005. }
  1006. static BOOL OnTV_SelectionChanged(HNAVCTRL hNav, NMTREEVIEWW *pnmtv)
  1007. {
  1008. if (hNav && ((NAVMNGR*)hNav)->fnOnItemSelected)
  1009. {
  1010. ((NAVMNGR*)hNav)->fnOnItemSelected(hNav, (HNAVITEM)pnmtv->itemOld.lParam, (HNAVITEM)pnmtv->itemNew.lParam);
  1011. MLSkinnedScrollWnd_UpdateBars(((NAVMNGR*)hNav)->hwndHost, TRUE);
  1012. }
  1013. return FALSE;
  1014. }
  1015. static BOOL OnTV_RightClick(HNAVCTRL hNav, NMHDR *pnmh, LRESULT *pResult)
  1016. {
  1017. return OnNavTree_Click(hNav, ACTION_CLICKR_I, pResult);
  1018. }
  1019. static BOOL OnTV_DoubleClick(HNAVCTRL hNav, NMHDR *pnmh, LRESULT *pResult)
  1020. {
  1021. return OnNavTree_Click(hNav, ACTION_DBLCLICKL_I, pResult);
  1022. }
  1023. static BOOL OnTV_KeyDown(HNAVCTRL hNav, NMTVKEYDOWN *ptvkd, LRESULT *pResult)
  1024. {
  1025. if (VK_RETURN == ptvkd->wVKey) return OnNavTree_Click(hNav, ACTION_ENTER_I, pResult);
  1026. if (hNav && ((NAVMNGR*)hNav)->fnOnKeyDown)
  1027. {
  1028. HNAVITEM hItem;
  1029. hItem = NavCtrlI_GetSelection(hNav);
  1030. if (hItem)
  1031. {
  1032. *pResult = ((NAVMNGR*)hNav)->fnOnKeyDown(hNav, hItem, ptvkd);
  1033. return (BOOL)*pResult;
  1034. }
  1035. }
  1036. return FALSE;
  1037. }
  1038. static BOOL OnTV_BeginLabelEdit(HNAVCTRL hNav, NMTVDISPINFOW *di, LRESULT *pResult)
  1039. {
  1040. NAVMNGR *manager;
  1041. NAVITM *item;
  1042. manager = (NAVMNGR*)hNav;
  1043. if (NULL == di)
  1044. return FALSE;
  1045. item = (NAVITM*)di->item.lParam;
  1046. *pResult = TRUE;
  1047. if (NULL != item &&
  1048. 0 != (NIS_ALLOWEDIT_I & item->style))
  1049. {
  1050. if (NULL == manager->fnOnBeginTitleEdit ||
  1051. FALSE != manager->fnOnBeginTitleEdit(hNav, (HNAVITEM)item))
  1052. {
  1053. HWND treeWindow, editWindow;
  1054. treeWindow = manager->hwndHost;
  1055. editWindow = (HWND)SendMessageW(treeWindow, TVM_GETEDITCONTROL, 0, 0);
  1056. if (NULL != editWindow)
  1057. SubclassEditControl(editWindow);
  1058. manager->style |= NAVSTYLE_EDITMODE;
  1059. *pResult = FALSE;
  1060. }
  1061. }
  1062. return TRUE;
  1063. }
  1064. static BOOL OnTV_EndLabelEdit(HNAVCTRL hNav, NMTVDISPINFOW *di, LRESULT *pResult)
  1065. {
  1066. NAVMNGR *manager;
  1067. manager = (NAVMNGR*)hNav;
  1068. manager->style &= ~NAVSTYLE_EDITMODE;
  1069. if (NULL != manager->fnOnEndTitleEdit &&
  1070. FALSE == manager->fnOnEndTitleEdit(hNav, (HNAVITEM)di->item.lParam, di->item.pszText))
  1071. {
  1072. *pResult = FALSE;
  1073. }
  1074. else
  1075. {
  1076. *pResult = (NULL != di->item.pszText) ?
  1077. NavItemI_SetText((HNAVITEM)di->item.lParam, di->item.pszText) :
  1078. FALSE;
  1079. }
  1080. return TRUE;
  1081. }
  1082. static BOOL OnTV_SetCursor(HNAVCTRL hNav, NMMOUSE *pm, LRESULT *pResult)
  1083. {
  1084. if (!pm->dwItemData)
  1085. {
  1086. TVHITTESTINFO hit;
  1087. if(GetCursorPos(&hit.pt))
  1088. {
  1089. HTREEITEM hTreeItem;
  1090. MapWindowPoints(HWND_DESKTOP, ((NAVMNGR*)hNav)->hwndHost, &hit.pt, 1);
  1091. hTreeItem = (HTREEITEM)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_HITTEST, (WPARAM)0, (LPARAM)&hit);
  1092. if (hTreeItem) pm->dwItemData = (DWORD_PTR)GetNavItemFromTreeItem(hNav, hTreeItem);
  1093. }
  1094. }
  1095. if (pm->dwItemData)
  1096. {
  1097. if ((NIS_WANTSETCURSOR_I & ((NAVITM*)pm->dwItemData)->style) && ((NAVMNGR*)hNav)->fnOnSetCursor)
  1098. {
  1099. *pResult = ((NAVMNGR*)hNav)->fnOnSetCursor(hNav, (HNAVITEM)pm->dwItemData, ((NAVITM*)pm->dwItemData)->lParam);
  1100. }
  1101. }
  1102. return TRUE;
  1103. }
  1104. static BOOL OnTV_SetFocus(HNAVCTRL hNav, NMHDR *pnmh)
  1105. {
  1106. NAVMNGR *manager = (NAVMNGR*)hNav;
  1107. if (NULL == manager)
  1108. return FALSE;
  1109. if (0 == (NAVSTYLE_FOCUSED & manager->style))
  1110. {
  1111. manager->style |= NAVSTYLE_FOCUSED;
  1112. HNAVITEM selectedItem = NavCtrlI_GetSelection(hNav);
  1113. if (NULL != selectedItem)
  1114. NavItemI_Invalidate(selectedItem, NULL, FALSE);
  1115. }
  1116. return TRUE;
  1117. }
  1118. static BOOL OnTV_KillFocus(HNAVCTRL hNav, NMHDR *pnmh)
  1119. {
  1120. NAVMNGR *manager = (NAVMNGR*)hNav;
  1121. if (NULL == manager)
  1122. return FALSE;
  1123. if (0 != (NAVSTYLE_FOCUSED & manager->style))
  1124. {
  1125. manager->style &= ~NAVSTYLE_FOCUSED;
  1126. HNAVITEM selectedItem = NavCtrlI_GetSelection(hNav);
  1127. if (NULL != selectedItem)
  1128. NavItemI_Invalidate(selectedItem, NULL, FALSE);
  1129. }
  1130. return TRUE;
  1131. }
  1132. // manager
  1133. HNAVCTRL NavCtrlI_Create(HWND hwndParent)
  1134. {
  1135. PNAVMNGR pMngr = (PNAVMNGR)calloc(1, sizeof(NAVMNGR));
  1136. if (!pMngr) return NULL;
  1137. pMngr->hwndHost = CreateWindowExW(WS_EX_NOPARENTNOTIFY | WS_EX_CLIENTEDGE,
  1138. WC_TREEVIEWW, L"",
  1139. WS_CHILD | WS_TABSTOP | TVS_SHOWSELALWAYS | TVS_FULLROWSELECT | TVS_NOHSCROLL | TVS_EDITLABELS,
  1140. 0, 0, 1, 1, hwndParent, NULL, NULL, NULL);
  1141. if (!IsWindow(pMngr->hwndHost) || !SetPropW(pMngr->hwndHost, NAVMGR_HWNDPROPW, pMngr))
  1142. {
  1143. NavCtrlI_Destroy(pMngr);
  1144. return NULL;
  1145. }
  1146. pMngr->lastUsedId = NAVITEM_RANGE_MIN;
  1147. pMngr->style = NAVSTYLE_DEFAULT;
  1148. SubclassTreeView(pMngr->hwndHost); // need to be before Skinning
  1149. if (SkinWindowEx(pMngr->hwndHost, SKINNEDWND_TYPE_SCROLLWND, SWS_USESKINFONT | SWS_USESKINCOLORS))
  1150. {
  1151. MLSkinnedScrollWnd_SetMode(pMngr->hwndHost, SCROLLMODE_TREEVIEW);
  1152. HWND hTooltip = (HWND)SendMessageW(pMngr->hwndHost, TVM_GETTOOLTIPS, 0, 0L);
  1153. if (NULL != hTooltip)
  1154. {
  1155. SkinWindowEx(hTooltip, SKINNEDWND_TYPE_TOOLTIP, SWS_USESKINFONT | SWS_USESKINCOLORS);
  1156. }
  1157. }
  1158. SendMessageW(pMngr->hwndHost, (TV_FIRST + 44)/*TVM_SETEXTENDEDSTYLE*/,
  1159. (WPARAM)pMngr->hwndHost, (LPARAM)0x0004/*TVS_EX_DOUBLEBUFFER*/);
  1160. SendMessageW(pMngr->hwndHost, CCM_SETVERSION, 6, 0);
  1161. SendMessageW(pMngr->hwndHost, TVM_SETSCROLLTIME, 200, 0);
  1162. return (HNAVCTRL)pMngr;
  1163. }
  1164. BOOL NavCtrlI_SetRect(HNAVCTRL hNav, RECT *prc)
  1165. {
  1166. return (hNav && prc) ? SetWindowPos(((NAVMNGR*)hNav)->hwndHost, NULL,
  1167. prc->left, prc->top, prc->right - prc->left, prc->bottom - prc->top,
  1168. SWP_NOACTIVATE | SWP_NOZORDER) : FALSE;
  1169. }
  1170. BOOL NavCtrlI_Show(HNAVCTRL hNav, INT nCmdShow)
  1171. {
  1172. return (hNav) ? ShowWindow(((NAVMNGR*)hNav)->hwndHost, nCmdShow) : FALSE;
  1173. }
  1174. BOOL NavCtrlI_Enable(HNAVCTRL hNav, BOOL fEnable)
  1175. {
  1176. return (hNav) ? EnableWindow(((NAVMNGR*)hNav)->hwndHost, fEnable) : FALSE;
  1177. }
  1178. BOOL NavCtrlI_Destroy(HNAVCTRL hNav)
  1179. {
  1180. if (!hNav) return FALSE;
  1181. if (NULL != ((NAVMNGR*)hNav)->fnOnDestroy)
  1182. {
  1183. ((NAVMNGR*)hNav)->fnOnDestroy(hNav);
  1184. }
  1185. NavCtrlI_SaveStates(hNav);
  1186. if (((NAVMNGR*)hNav)->hwndHost)
  1187. {
  1188. RemovePropW(((NAVMNGR*)hNav)->hwndHost, NAVMGR_HWNDPROPW);
  1189. DestroyWindow(((NAVMNGR*)hNav)->hwndHost);
  1190. }
  1191. NavCtrlI_DeleteStates(hNav);
  1192. free(hNav);
  1193. return TRUE;
  1194. }
  1195. BOOL NavCtrlI_Update(HNAVCTRL hNav)
  1196. {
  1197. return (hNav) ? UpdateWindow(((NAVMNGR*)hNav)->hwndHost) : FALSE;
  1198. }
  1199. C_Config *NavCtrlI_SetConfig(HNAVCTRL hNav, C_Config *pConfig)
  1200. {
  1201. C_Config *pTemp;
  1202. if (!hNav) return NULL;
  1203. pTemp = ((NAVMNGR*)hNav)->pConfig;
  1204. ((NAVMNGR*)hNav)->pConfig = pConfig;
  1205. if (pConfig) NavCtrlI_LoadStates(hNav);
  1206. return pTemp;
  1207. }
  1208. HWND NavCtrlI_GetHWND(HNAVCTRL hNav)
  1209. {
  1210. return (hNav) ? ((NAVMNGR*)hNav)->hwndHost : NULL;
  1211. }
  1212. BOOL NavCtrlI_ProcessNotifications(HNAVCTRL hNav, LPNMHDR pnmh, LRESULT *pResult)
  1213. {
  1214. if (!hNav || pnmh->hwndFrom != ((PNAVMNGR)hNav)->hwndHost) return FALSE;
  1215. switch(pnmh->code)
  1216. {
  1217. case TVN_KEYDOWN: return OnTV_KeyDown(hNav, (NMTVKEYDOWN*)pnmh, pResult);
  1218. case TVN_SELCHANGEDW: return OnTV_SelectionChanged(hNav, (NMTREEVIEWW*)pnmh);
  1219. case NM_RCLICK: return OnTV_RightClick(hNav, pnmh, pResult);
  1220. case NM_DBLCLK: return OnTV_DoubleClick(hNav, pnmh, pResult);
  1221. case TVN_BEGINDRAGW: return OnTV_BeginDrag(hNav, (NMTREEVIEWW*)pnmh);
  1222. case NM_CLICK: return OnTV_Click(hNav, pnmh, pResult);
  1223. case TVN_GETDISPINFOW: return OnTV_GetDispInfo(hNav, (NMTVDISPINFOW*)pnmh, pResult);
  1224. case NM_CUSTOMDRAW: return OnTV_CustomDraw(hNav, (NMTVCUSTOMDRAW*)pnmh, pResult);
  1225. case TVN_DELETEITEMW: return OnTV_DeleteItem(hNav, &((NMTREEVIEWW*)pnmh)->itemOld);
  1226. case TVN_BEGINLABELEDITW: return OnTV_BeginLabelEdit(hNav, (NMTVDISPINFOW*)pnmh, pResult);
  1227. case TVN_ENDLABELEDITW: return OnTV_EndLabelEdit(hNav, (NMTVDISPINFOW*)pnmh, pResult);
  1228. case NM_SETCURSOR: return OnTV_SetCursor(hNav, (NMMOUSE*)pnmh, pResult);
  1229. case NM_SETFOCUS: return OnTV_SetFocus(hNav, pnmh);
  1230. case NM_KILLFOCUS: return OnTV_KillFocus(hNav, pnmh);
  1231. }
  1232. return FALSE;
  1233. }
  1234. LPVOID NavCtrlI_RegisterCallback(HNAVCTRL hNav, LPVOID fnCallback, INT cbType)
  1235. {
  1236. LPVOID temp;
  1237. if (!hNav) return NULL;
  1238. switch(cbType)
  1239. {
  1240. case CALLBACK_ONCLICK_I:
  1241. temp = ((NAVMNGR*)hNav)->fnOnItemClick;
  1242. ((NAVMNGR*)hNav)->fnOnItemClick = (ONNAVITEMCLICK_I)fnCallback;
  1243. return temp;
  1244. case CALLBACK_ONSELECTED_I:
  1245. temp = ((NAVMNGR*)hNav)->fnOnItemSelected;
  1246. ((NAVMNGR*)hNav)->fnOnItemSelected = (ONNAVITEMSELECTED_I)fnCallback;
  1247. return temp;
  1248. case CALLBACK_ONKEYDOWN_I:
  1249. temp = ((NAVMNGR*)hNav)->fnOnKeyDown;
  1250. ((NAVMNGR*)hNav)->fnOnKeyDown = (ONNAVCTRLKEYDOWN_I)fnCallback;
  1251. return temp;
  1252. case CALLBACK_ONBEGINDRAG_I:
  1253. temp = ((NAVMNGR*)hNav)->fnOnBeginDrag;
  1254. ((NAVMNGR*)hNav)->fnOnBeginDrag = (ONNAVCTRLBEGINDRAG_I)fnCallback;
  1255. return temp;
  1256. case CALLBACK_ONDESTROY_I:
  1257. temp = ((NAVMNGR*)hNav)->fnOnDestroy;
  1258. ((NAVMNGR*)hNav)->fnOnDestroy = (ONNAVCTRLDESTROY_I)fnCallback;
  1259. return temp;
  1260. case CALLBACK_ONGETIMAGEINDEX_I:
  1261. temp = ((NAVMNGR*)hNav)->fnOnItemGetImageIndex;
  1262. ((NAVMNGR*)hNav)->fnOnItemGetImageIndex = (ONNAVITEMGETIMAGEINDEX_I)fnCallback;
  1263. return temp;
  1264. case CALLBACK_ONBEGINTITLEEDIT_I:
  1265. temp = ((NAVMNGR*)hNav)->fnOnBeginTitleEdit;
  1266. ((NAVMNGR*)hNav)->fnOnBeginTitleEdit = (ONNAVITEMBEGINTITLEEDIT_I)fnCallback;
  1267. return temp;
  1268. case CALLBACK_ONENDTITLEEDIT_I:
  1269. temp = ((NAVMNGR*)hNav)->fnOnEndTitleEdit;
  1270. ((NAVMNGR*)hNav)->fnOnEndTitleEdit = (ONNAVCTRLENDTITLEEDIT_I)fnCallback;
  1271. return temp;
  1272. case CALLBACK_ONITEMDELETE_I:
  1273. temp = ((NAVMNGR*)hNav)->fnOnItemDelete;
  1274. ((NAVMNGR*)hNav)->fnOnItemDelete = (ONNAVITEMDELETE_I)fnCallback;
  1275. return temp;
  1276. case CALLBACK_ONITEMDRAW_I:
  1277. temp = ((NAVMNGR*)hNav)->fnOnCustomDraw;
  1278. ((NAVMNGR*)hNav)->fnOnCustomDraw = (ONNAVITEMDRAW_I)fnCallback;
  1279. return temp;
  1280. case CALLBACK_ONSETCURSOR_I:
  1281. temp = ((NAVMNGR*)hNav)->fnOnSetCursor;
  1282. ((NAVMNGR*)hNav)->fnOnSetCursor = (ONNAVITEMSETCURSOR_I)fnCallback;
  1283. return temp;
  1284. case CALLBACK_ONHITTEST_I:
  1285. temp = ((NAVMNGR*)hNav)->fnOnHitTest;
  1286. ((NAVMNGR*)hNav)->fnOnHitTest = (ONNAVITEMHITTEST_I)fnCallback;
  1287. return temp;
  1288. }
  1289. return NULL;
  1290. }
  1291. BOOL NavCtrlI_UpdateLook(HNAVCTRL hNav)
  1292. {
  1293. INT minHeight;
  1294. if (!hNav || !((NAVMNGR*)hNav)->hwndHost) return FALSE;
  1295. minHeight = -1;
  1296. SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_SETBKCOLOR, (WPARAM)0, (LPARAM)WADlg_getColor(WADLG_ITEMBG));
  1297. SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_SETTEXTCOLOR, (WPARAM)0, (LPARAM)WADlg_getColor(WADLG_ITEMFG));
  1298. SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_SETINSERTMARKCOLOR, (WPARAM)0, (LPARAM)WADlg_getColor(WADLG_ITEMFG));
  1299. MLSkinnedWnd_SkinChanged(((NAVMNGR*)hNav)->hwndHost, FALSE, FALSE);
  1300. HFONT hFont = (HFONT)SendMessageW(((NAVMNGR*)hNav)->hwndHost, WM_GETFONT, 0, 0L);
  1301. HDC hdc;
  1302. hdc = GetDCEx(((NAVMNGR*)hNav)->hwndHost, NULL, DCX_CACHE);
  1303. if (hdc)
  1304. {
  1305. if (NULL == hFont)
  1306. hFont = (HFONT)MlStockObjects_Get(DEFAULT_FONT);
  1307. TEXTMETRICW tm;
  1308. if (hFont)
  1309. {
  1310. HFONT hfntOld = (HFONT)SelectObject(hdc, hFont);
  1311. if (GetTextMetricsW(hdc, &tm)) minHeight = tm.tmHeight + 2/*Borders*/;
  1312. SelectObject(hdc, hfntOld);
  1313. }
  1314. ReleaseDC(((NAVMNGR*)hNav)->hwndHost, hdc);
  1315. }
  1316. if (((NAVMNGR*)hNav)->pConfig)
  1317. {
  1318. BOOL fFullRowSelect;
  1319. DWORD dwWndStyle;
  1320. INT height;
  1321. height = ((NAVMNGR*)hNav)->pConfig->ReadInt(L"Navigation_ItemHeight", 18);
  1322. if (minHeight > 0 && height < minHeight) height = minHeight;
  1323. SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_SETITEMHEIGHT, (WPARAM)height, (LPARAM)0);
  1324. ((NAVMNGR*)hNav)->style = (((NAVMNGR*)hNav)->style & ~NAVSTYLE_MOUSEDOWNSELECT) | ((0 != ((NAVMNGR*)hNav)->pConfig->ReadInt(L"Navigation_MouseDownSel", 0)) ? NAVSTYLE_MOUSEDOWNSELECT : 0);
  1325. fFullRowSelect = (((NAVMNGR*)hNav)->pConfig->ReadInt(L"Navigation_FullRowSel", 1) != 0);
  1326. dwWndStyle = (DWORD)GetWindowLongPtrW(((NAVMNGR*)hNav)->hwndHost, GWL_STYLE);
  1327. if (fFullRowSelect != (TVS_FULLROWSELECT == (TVS_FULLROWSELECT & dwWndStyle)))
  1328. {
  1329. SetWindowLongPtrW(((NAVMNGR*)hNav)->hwndHost, GWL_STYLE,
  1330. (dwWndStyle & ~TVS_FULLROWSELECT) | ((fFullRowSelect) ? TVS_FULLROWSELECT : 0));
  1331. }
  1332. NavCtrlI_SetImageList(hNav, ((NAVMNGR*)hNav)->hmlilImages);
  1333. }
  1334. return TRUE;
  1335. }
  1336. HMLIMGLST NavCtrlI_SetImageList(HNAVCTRL hNav, HMLIMGLST hmlil)
  1337. {
  1338. HMLIMGLST hmlilOld;
  1339. HIMAGELIST hilTree, hilNew;
  1340. if (!hNav) return NULL;
  1341. hmlilOld = ((NAVMNGR*)hNav)->hmlilImages;
  1342. ((NAVMNGR*)hNav)->hmlilImages = hmlil;
  1343. hilNew = MLImageListI_GetRealList(hmlil);
  1344. hilTree = (HIMAGELIST)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETIMAGELIST, (WPARAM)TVSIL_NORMAL, (LPARAM)0);
  1345. if (!((NAVMNGR*)hNav)->pConfig || ((NAVMNGR*)hNav)->pConfig->ReadInt(L"Navigation_ShowIcons", 1))
  1346. {
  1347. if (hilTree != hilNew) SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_SETIMAGELIST, (WPARAM)TVSIL_NORMAL, (LPARAM)hilNew);
  1348. }
  1349. else if (hilTree) SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_SETIMAGELIST, (WPARAM)TVSIL_NORMAL, (LPARAM)NULL);
  1350. return hmlilOld;
  1351. }
  1352. HMLIMGLST NavCtrlI_GetImageList(HNAVCTRL hNav)
  1353. {
  1354. return (hNav) ? ((NAVMNGR*)hNav)->hmlilImages : NULL;
  1355. }
  1356. HNAVITEM NavCtrlI_FindItem(HNAVCTRL hNav, INT itemId)
  1357. {
  1358. return (hNav) ? FindNavItemByNavIdEx(((NAVMNGR*)hNav)->hwndHost, itemId, TVI_ROOT) : NULL;
  1359. }
  1360. HNAVITEM NavCtrlI_FindItemByName(HNAVCTRL hNav, LCID Locale, UINT compFlags, LPCWSTR pszName, INT cchLength)
  1361. {
  1362. TREEITEMSEARCH search;
  1363. if (!hNav || !pszName || !((NAVMNGR*)hNav)->hwndHost) return NULL;
  1364. search.fFound = FALSE;
  1365. search.itemData = (INT_PTR)pszName;
  1366. search.item.mask = TVIF_PARAM;
  1367. search.flags = compFlags;
  1368. // pack extra info
  1369. search.item.cchTextMax = cchLength;
  1370. search.item.state = Locale;
  1371. EnumerateTreeItems(((NAVMNGR*)hNav)->hwndHost, TVI_ROOT, FindTreeItemByNameCB, &search);
  1372. return (search.fFound) ? (HNAVITEM)search.item.lParam : NULL;
  1373. }
  1374. HNAVITEM NavCtrlI_FindItemByFullName(HNAVCTRL hNav, LCID Locale, UINT compFlags, LPCWSTR pszFullName, INT cchLength, BOOL fAncestorOk)
  1375. {
  1376. INT len, separatorCount;
  1377. WCHAR shortname[ITEM_SHORTNAME_MAX] = {0};
  1378. LPCWSTR end;
  1379. TVITEMW treeItem;
  1380. HNAVITEM hNavParent;
  1381. if (!hNav || !pszFullName || !((NAVMNGR*)hNav)->hwndHost) return NULL;
  1382. hNavParent = NULL;
  1383. len = (cchLength < 0)? lstrlenW(pszFullName) : cchLength;
  1384. if (!len) return NULL;
  1385. end = pszFullName + len;
  1386. ZeroMemory(&treeItem, sizeof(TVITEMW));
  1387. treeItem.mask = TVIF_PARAM;
  1388. len = 0;
  1389. separatorCount = 0;
  1390. while (pszFullName != end + 1)
  1391. {
  1392. if (pszFullName == end) { separatorCount++; }
  1393. if (SEPARATOR == *pszFullName) separatorCount++;
  1394. else
  1395. {
  1396. if (separatorCount)
  1397. {
  1398. INT i;
  1399. for (i = separatorCount/2; i > 0; i--)
  1400. {
  1401. if (len == ITEM_SHORTNAME_MAX -1) return NULL; // ugh...
  1402. shortname[len++] = SEPARATOR;
  1403. }
  1404. if (separatorCount%2 && len)
  1405. {
  1406. if (CSTR_EQUAL != CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, EMPTY_ITEM_NAME, -1, shortname, len))
  1407. {
  1408. treeItem.hItem = (HTREEITEM)((NULL == hNavParent) ?
  1409. SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETNEXTITEM, (WPARAM)TVGN_ROOT, (LPARAM)0) :
  1410. SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETNEXTITEM, (WPARAM)TVGN_CHILD, (LPARAM)((NAVITM*)hNavParent)->hTreeItem));
  1411. while(treeItem.hItem)
  1412. {
  1413. if (SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETITEMW, (WPARAM)0, (LPARAM)&treeItem))
  1414. {
  1415. if (CSTR_EQUAL == CompareItemName(Locale, compFlags, shortname, len, (HNAVITEM)treeItem.lParam))
  1416. { // found!!!
  1417. if (pszFullName == end) return (HNAVITEM)treeItem.lParam;
  1418. break;
  1419. }
  1420. }
  1421. treeItem.hItem = (HTREEITEM)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETNEXTITEM, (WPARAM)TVGN_NEXT, (LPARAM)treeItem.hItem);
  1422. }
  1423. if (treeItem.hItem)
  1424. {
  1425. hNavParent = (HNAVITEM)treeItem.lParam;
  1426. if (!hNavParent) return NULL; // thats bad
  1427. }
  1428. else return (fAncestorOk) ? hNavParent : NULL;
  1429. }
  1430. len = 0;
  1431. }
  1432. separatorCount = 0;
  1433. }
  1434. if (len == ITEM_SHORTNAME_MAX -1) return NULL; // ugh...
  1435. shortname[len++] = *pszFullName;
  1436. }
  1437. pszFullName++;
  1438. }
  1439. return NULL;
  1440. }
  1441. HNAVITEM NavCtrlI_InsertItem(HNAVCTRL hNav, HNAVITEM hInsertAfter, HNAVITEM hParent, NAVITEM_I *pnis)
  1442. {
  1443. TVINSERTSTRUCTW is = {0};
  1444. NAVITM *pNavItem = 0;
  1445. HTREEITEM hItem = 0;
  1446. if (!pnis) return NULL;
  1447. if (NIMF_ITEMID_I & pnis->mask) { if (NavCtrlI_FindItem(hNav, pnis->id)) return NULL; }
  1448. else pnis->id = GetNextFreeItemId(hNav);
  1449. if (!pnis->id) return NULL;
  1450. pNavItem = (NAVITM*)calloc(1, sizeof(NAVITM));
  1451. if (!pNavItem) return NULL;
  1452. is.hParent = (hParent) ? ((NAVITM*)hParent)->hTreeItem : TVI_ROOT;
  1453. is.hInsertAfter = TVI_LAST;
  1454. if (NCI_LAST_I == hInsertAfter) is.hInsertAfter = TVI_LAST;
  1455. else if (NCI_FIRST_I == hInsertAfter) is.hInsertAfter = TVI_FIRST;
  1456. else if (hInsertAfter && !IS_NAVITEMSORTORDER(hInsertAfter)) is.hInsertAfter = ((NAVITM*)hInsertAfter)->hTreeItem;
  1457. if (is.hInsertAfter == is.hParent) is.hInsertAfter = TVI_FIRST;
  1458. pNavItem->id = pnis->id;
  1459. pNavItem->hwndTree = ((NAVMNGR*)hNav)->hwndHost;
  1460. is.item.mask = TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_TEXT;
  1461. is.item.lParam = (LPARAM)pNavItem;
  1462. is.item.pszText = LPSTR_TEXTCALLBACKW;
  1463. is.item.iImage = I_IMAGECALLBACK;
  1464. is.item.iSelectedImage = I_IMAGECALLBACK;
  1465. is.item.cChildren = I_CHILDRENCALLBACK;
  1466. if (NIMF_STYLE_I & pnis->mask) NavItemI_SetStyle(pNavItem, pnis->style, pnis->styleMask);
  1467. if (NIMF_TEXT_I & pnis->mask) NavItemI_SetText(pNavItem, pnis->pszText);
  1468. if (NIMF_TEXTINVARIANT_I & pnis->mask) NavItemI_SetInvariantText(pNavItem, pnis->pszInvariant);
  1469. if (NIMF_FONT_I & pnis->mask) NavItemI_SetFont(pNavItem, pnis->hFont);
  1470. if (NIMF_PARAM_I & pnis->mask) pNavItem->lParam = pnis->lParam;
  1471. NavItemI_SetImageIndex(pNavItem, (NIMF_IMAGE_I & pnis->mask) ? pnis->iImage : -1, IMAGE_NORMAL_I);
  1472. NavItemI_SetImageIndex(pNavItem, (NIMF_IMAGESEL_I & pnis->mask) ? pnis->iSelectedImage : -1, IMAGE_SELECTED_I);
  1473. NavCtrlI_BeginUpdate(hNav, NUF_LOCK_SELECTED_I);
  1474. hItem = (HTREEITEM)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_INSERTITEMW, (WPARAM)0, (LPARAM)&is);
  1475. if (hItem)
  1476. {
  1477. UINT state, stateMask;
  1478. NAVITEMSTATEREC *pRec;
  1479. BOOL itemRecSearched;
  1480. WORD order;
  1481. UINT flags;
  1482. pNavItem->hTreeItem = hItem;
  1483. itemRecSearched = FALSE;
  1484. order = (WORD)-1;
  1485. flags = NOF_MOVEAFTER_I;
  1486. if (hInsertAfter)
  1487. {
  1488. if (IS_NAVITEMSORTORDER(hInsertAfter)) { order = (WORD)hInsertAfter; flags = NOF_MOVEONEAFTER_I; }
  1489. else
  1490. {
  1491. HTREEITEM hTreePrev;
  1492. hTreePrev = (HTREEITEM)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETNEXTITEM, (WPARAM)TVGN_PREVIOUS, (LPARAM)hItem);
  1493. if (!hTreePrev) { order = 1; flags = NOF_MOVEONEBEFORE_I; }
  1494. else
  1495. {
  1496. HNAVITEM hPrev;
  1497. hPrev = GetNavItemFromTreeItem(hNav, hTreePrev);
  1498. order = (hPrev) ? ((NAVITM*)hPrev)->sortOrder : (WORD)-1;
  1499. flags = NOF_MOVEONEAFTER_I;
  1500. }
  1501. }
  1502. }
  1503. else
  1504. {
  1505. if (TVI_ROOT == is.hParent || !is.hParent)
  1506. {
  1507. pRec = NavCtrlI_FindItemStateRec(hNav, pNavItem, TRUE);
  1508. order = (pRec) ? pRec->nOrder : ++((NAVMNGR*)hNav)->lastOrderIndex;
  1509. flags = NOF_MOVEAFTER_I;
  1510. itemRecSearched = TRUE;
  1511. }
  1512. }
  1513. NavItemI_SetOrder(pNavItem, order, flags);
  1514. if (NIMF_STATE_I & pnis->mask)
  1515. {
  1516. state = pnis->state;
  1517. stateMask = pnis->stateMask;
  1518. }
  1519. else
  1520. {
  1521. state = 0;
  1522. stateMask = 0;
  1523. }
  1524. if (0 == (NIS_EXPANDED_I & stateMask))
  1525. {
  1526. if (!itemRecSearched) pRec = NavCtrlI_FindItemStateRec(hNav, pNavItem, TRUE);
  1527. state |= (pRec && pRec->fCollapsed) ? 0 : NIS_EXPANDED_I;
  1528. stateMask |= NIS_EXPANDED_I;
  1529. }
  1530. NavItemI_SetState(pNavItem, state, stateMask);
  1531. }
  1532. else
  1533. {
  1534. NavItemI_SetText(pNavItem, NULL);
  1535. NavItemI_SetInvariantText(pNavItem, NULL);
  1536. free(pNavItem);
  1537. pNavItem = NULL;
  1538. }
  1539. NavCtrlI_EndUpdate(hNav);
  1540. return (HNAVITEM)pNavItem;
  1541. }
  1542. BOOL NavCtrlI_DeleteItem(HNAVCTRL hNav, HNAVITEM hItem)
  1543. {
  1544. return (hNav && hItem) ? (BOOL)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_DELETEITEM, 0, (LPARAM)((NAVITM*)hItem)->hTreeItem) : FALSE;
  1545. }
  1546. BOOL NavCtrlI_DeleteAll(HNAVCTRL hNav)
  1547. {
  1548. return (hNav) ? (BOOL)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT) : FALSE;
  1549. }
  1550. HNAVITEM NavCtrlI_GetRoot(HNAVCTRL hNav)
  1551. {
  1552. HTREEITEM hTreeChild;
  1553. if (!hNav) return NULL;
  1554. hTreeChild = (HTREEITEM)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETNEXTITEM, (WPARAM)TVGN_ROOT, (LPARAM)0L);
  1555. return (hTreeChild) ? GetNavItemFromTreeItem(hNav, hTreeChild) : NULL;
  1556. }
  1557. HNAVITEM NavCtrlI_GetSelection(HNAVCTRL hNav)
  1558. {
  1559. HTREEITEM hTreeChild;
  1560. if (!hNav) return NULL;
  1561. hTreeChild = (HTREEITEM)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETNEXTITEM, (WPARAM)TVGN_CARET, (LPARAM)0L);
  1562. return (hTreeChild) ? GetNavItemFromTreeItem(hNav, hTreeChild) : NULL;
  1563. }
  1564. HNAVITEM NavCtrlI_GetFirstVisible(HNAVCTRL hNav)
  1565. {
  1566. HTREEITEM hTreeChild;
  1567. if (!hNav) return NULL;
  1568. hTreeChild = (HTREEITEM)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETNEXTITEM, (WPARAM)TVGN_FIRSTVISIBLE, (LPARAM)0L);
  1569. return (hTreeChild) ? GetNavItemFromTreeItem(hNav, hTreeChild) : NULL;
  1570. }
  1571. HNAVITEM NavCtrlI_GetLastVisible(HNAVCTRL hNav)
  1572. {
  1573. HTREEITEM hTreeChild;
  1574. if (!hNav) return NULL;
  1575. hTreeChild = (HTREEITEM)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETNEXTITEM, (WPARAM)TVGN_LASTVISIBLE, (LPARAM)0L);
  1576. return (hTreeChild) ? GetNavItemFromTreeItem(hNav, hTreeChild) : NULL;
  1577. }
  1578. HNAVITEM NavCtrlI_HitTest(HNAVCTRL hNav, POINT *ppt, UINT *pFlags)
  1579. {
  1580. TVHITTESTINFO tvhi;
  1581. HNAVITEM hItem;
  1582. if (!hNav || !((NAVMNGR*)hNav)->hwndHost || !ppt)
  1583. {
  1584. if (pFlags) *pFlags = NAVHT_NOWHERE_I;
  1585. return NULL;
  1586. }
  1587. tvhi.pt = *ppt;
  1588. SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_HITTEST, (WPARAM)0, (LPARAM)&tvhi);
  1589. hItem = (tvhi.hItem) ? GetNavItemFromTreeItem(hNav, tvhi.hItem) : NULL;
  1590. PerformCustomHitTest(hNav, tvhi.pt, &tvhi.flags, (hItem) ? &hItem : NULL);
  1591. if (pFlags) *pFlags = tvhi.flags;
  1592. return hItem;
  1593. }
  1594. BOOL NavCtrlI_SetInsertMark(HNAVCTRL hNav, HNAVITEM hItem, BOOL fAfter)
  1595. {
  1596. return (hNav) ? (BOOL)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_SETINSERTMARK,
  1597. (WPARAM)fAfter,
  1598. (hItem) ? (LPARAM)((NAVITM*)hItem)->hTreeItem : NULL) : FALSE;
  1599. }
  1600. BOOL NavCtrlI_EnumItems(HNAVCTRL hNav, NAVENUMPROC_I pEnumFunc, HNAVITEM hItemStart, LPARAM lParam)
  1601. {
  1602. NAVENUMSTRUCT navenum;
  1603. if (!hNav || !pEnumFunc) return FALSE;
  1604. navenum.hNav = hNav;
  1605. navenum.callback = pEnumFunc;
  1606. navenum.lParam = lParam;
  1607. navenum.item.mask = TVIF_PARAM;
  1608. return EnumerateTreeItems(((NAVMNGR*)hNav)->hwndHost, (hItemStart) ? ((NAVITM*)hItemStart)->hTreeItem : TVI_ROOT, EnumNavItemCB, &navenum);
  1609. }
  1610. INT NavCtrlI_BeginUpdate(HNAVCTRL hNav, UINT fRememberPos)
  1611. {
  1612. if (!hNav || !((NAVMNGR*)hNav)->hwndHost || !IsWindow(((NAVMNGR*)hNav)->hwndHost)) return -1;
  1613. if (!((NAVMNGR*)hNav)->lockUpdate)
  1614. {
  1615. ((NAVMNGR*)hNav)->lockFirst = NULL;
  1616. ((NAVMNGR*)hNav)->lockSelected = NULL;
  1617. if (fRememberPos)
  1618. {
  1619. ((NAVMNGR*)hNav)->lockFirst = (HTREEITEM)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETNEXTITEM, TVGN_FIRSTVISIBLE, (LPARAM)TVI_ROOT);
  1620. if (NUF_LOCK_SELECTED_I & fRememberPos)
  1621. {
  1622. ((NAVMNGR*)hNav)->lockSelected = (HTREEITEM)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETNEXTITEM, TVGN_CARET, (LPARAM)TVI_ROOT);
  1623. if (((NAVMNGR*)hNav)->lockSelected)
  1624. {
  1625. RECT rc;
  1626. *(HTREEITEM*)&rc = ((NAVMNGR*)hNav)->lockSelected;
  1627. if (!SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETITEMRECT, FALSE, (LPARAM)&rc)) ((NAVMNGR*)hNav)->lockSelected = NULL;
  1628. else ((NAVMNGR*)hNav)->lockSelPos = rc.top;
  1629. }
  1630. }
  1631. }
  1632. UpdateWindow(((NAVMNGR*)hNav)->hwndHost);
  1633. SendMessageW(((NAVMNGR*)hNav)->hwndHost, WM_SETREDRAW, (WPARAM)FALSE, 0L);
  1634. }
  1635. return ++((NAVMNGR*)hNav)->lockUpdate;
  1636. }
  1637. INT NavCtrlI_EndUpdate(HNAVCTRL hNav)
  1638. {
  1639. if (!hNav || !((NAVMNGR*)hNav)->hwndHost || !IsWindow(((NAVMNGR*)hNav)->hwndHost)) return -1;
  1640. if (((NAVMNGR*)hNav)->lockUpdate)
  1641. {
  1642. ((NAVMNGR*)hNav)->lockUpdate--;
  1643. if (!((NAVMNGR*)hNav)->lockUpdate)
  1644. {
  1645. SCROLLINFO si;
  1646. si.cbSize = sizeof(SCROLLINFO);
  1647. si.fMask = SIF_POS | SIF_RANGE;
  1648. if (((NAVMNGR*)hNav)->lockSelected)
  1649. {
  1650. RECT rc;
  1651. *(HTREEITEM*)&rc = ((NAVMNGR*)hNav)->lockSelected;
  1652. if (!SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETITEMRECT, FALSE, (LPARAM)&rc))
  1653. {
  1654. SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_SELECTITEM, (WPARAM)TVGN_FIRSTVISIBLE, (LPARAM)((NAVMNGR*)hNav)->lockSelected);
  1655. }
  1656. else if (((NAVMNGR*)hNav)->lockSelPos != rc.top)
  1657. {
  1658. INT iHeight = (INT)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETITEMHEIGHT , 0, 0L);
  1659. if (iHeight)
  1660. {
  1661. INT pos, oldPos;
  1662. if (((NAVMNGR*)hNav)->lockSelPos > rc.top) iHeight = 0 - iHeight;
  1663. WPARAM wCmd = MAKEWPARAM((((NAVMNGR*)hNav)->lockSelPos > rc.top) ? SB_LINEUP : SB_LINEDOWN, 0);
  1664. oldPos = 0xFFFFFF;
  1665. for(pos = ((NAVMNGR*)hNav)->lockSelPos; pos != rc.top; pos += iHeight)
  1666. {
  1667. if (ABS((oldPos - rc.top)) <= ABS((pos - rc.top))) break;
  1668. oldPos = pos;
  1669. SendMessageW(((NAVMNGR*)hNav)->hwndHost, WM_VSCROLL, wCmd, 0L);
  1670. SendMessageW(((NAVMNGR*)hNav)->hwndHost, WM_VSCROLL, MAKEWPARAM(SB_ENDSCROLL, 0), 0L);
  1671. }
  1672. }
  1673. }
  1674. }
  1675. else if (((NAVMNGR*)hNav)->lockFirst)
  1676. {
  1677. SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_ENSUREVISIBLE, (WPARAM)0, (LPARAM)((NAVMNGR*)hNav)->lockFirst);
  1678. }
  1679. ((NAVMNGR*)hNav)->lockFirst = NULL;
  1680. ((NAVMNGR*)hNav)->lockSelected = NULL;
  1681. if(GetScrollInfo(((NAVMNGR*)hNav)->hwndHost, SB_HORZ, &si) && (si.nMin != si.nPos))
  1682. {
  1683. SendMessageW(((NAVMNGR*)hNav)->hwndHost, WM_HSCROLL, MAKEWPARAM(SB_LEFT, 0), NULL);
  1684. SendMessageW(((NAVMNGR*)hNav)->hwndHost, WM_HSCROLL, MAKEWPARAM(SB_ENDSCROLL, 0), NULL);
  1685. }
  1686. SendMessageW(((NAVMNGR*)hNav)->hwndHost, WM_SETREDRAW, (WPARAM)TRUE, 0L);
  1687. }
  1688. }
  1689. return ((NAVMNGR*)hNav)->lockUpdate;
  1690. }
  1691. INT NavCtrlI_MapPointsTo(HNAVCTRL hNav, HWND hwndTo, POINT *ppt, UINT cPoints)
  1692. {
  1693. return (hNav) ? MapWindowPoints(((NAVMNGR*)hNav)->hwndHost, hwndTo, ppt, cPoints) : 0;
  1694. }
  1695. INT NavCtrlI_MapPointsFrom(HNAVCTRL hNav, HWND hwndFrom, POINT *ppt, UINT cPoints)
  1696. {
  1697. return (hNav) ? MapWindowPoints(hwndFrom, ((NAVMNGR*)hNav)->hwndHost, ppt, cPoints) : 0;
  1698. }
  1699. BOOL NavCtrlI_EndEditTitle(HNAVCTRL hNav, BOOL fCancel)
  1700. {
  1701. return (hNav) ? (BOOL)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_ENDEDITLABELNOW, (WPARAM)fCancel, 0L) : FALSE;
  1702. }
  1703. INT NavCtrlI_GetIndent(HNAVCTRL hNav)
  1704. {
  1705. return (hNav) ? (BOOL)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETINDENT, (WPARAM)0, 0L) : 0;
  1706. }
  1707. DWORD NavCtrlI_GetStyle(HNAVCTRL hNav)
  1708. {
  1709. DWORD style;
  1710. style = NCS_NORMAL_I;
  1711. if (hNav)
  1712. {
  1713. if (TVS_FULLROWSELECT == (TVS_FULLROWSELECT & (DWORD)GetWindowLongPtrW(((NAVMNGR*)hNav)->hwndHost, GWL_STYLE)))
  1714. style |= NCS_FULLROWSELECT_I;
  1715. if (NULL != (HIMAGELIST)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETIMAGELIST, (WPARAM)TVSIL_NORMAL, (LPARAM)0))
  1716. style |= NCS_SHOWICONS_I;
  1717. }
  1718. return style;
  1719. }
  1720. BOOL NavItemI_EditTitle(HNAVITEM hItem)
  1721. {
  1722. NAVITM *item;
  1723. HWND editWindow;
  1724. if (NULL == hItem)
  1725. return FALSE;
  1726. item = (NAVITM*)hItem;
  1727. if (0 == (NIS_ALLOWEDIT_I & item->style))
  1728. return FALSE;
  1729. SendMessageW(item->hwndTree, TVM_ENSUREVISIBLE, 0, (LPARAM)item->hTreeItem);
  1730. editWindow = (HWND)SendMessageW(item->hwndTree, TVM_EDITLABELW, 0, (LPARAM)item->hTreeItem);
  1731. return (NULL != editWindow);
  1732. }
  1733. INT NavItemI_GetId(HNAVITEM hItem)
  1734. {
  1735. return (hItem) ? ((NAVITM*)hItem)->id : 0;
  1736. }
  1737. HNAVITEM NavItemI_GetChild(HNAVITEM hItem)
  1738. {
  1739. return NavItemI_GetNextEx(hItem, TVGN_CHILD);
  1740. }
  1741. HNAVITEM NavItemI_GetNext(HNAVITEM hItem)
  1742. {
  1743. return NavItemI_GetNextEx(hItem, TVGN_NEXT);
  1744. }
  1745. HNAVITEM NavItemI_GetRoot(HNAVITEM hItem)
  1746. {
  1747. return NavItemI_GetNextEx(hItem, TVGN_ROOT);
  1748. }
  1749. HNAVITEM NavItemI_GetParent(HNAVITEM hItem)
  1750. {
  1751. return NavItemI_GetNextEx(hItem, TVGN_PARENT);
  1752. }
  1753. HNAVITEM NavItemI_GetPrevious(HNAVITEM hItem)
  1754. {
  1755. return NavItemI_GetNextEx(hItem, TVGN_PREVIOUS);
  1756. }
  1757. INT NavItemI_GetChildrenCount(HNAVITEM hItem)
  1758. {
  1759. HTREEITEM hChild;
  1760. int counter;
  1761. if (!hItem) return -1;
  1762. hChild = (HTREEITEM)SendMessageW(((NAVITM*)hItem)->hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_CHILD, (LPARAM)((NAVITM*)hItem)->hTreeItem);
  1763. if (!hChild) return 0;
  1764. counter = 1;
  1765. while(NULL != (hChild = (HTREEITEM)SendMessageW(((NAVITM*)hItem)->hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_NEXT, (LPARAM)hChild))) counter++;
  1766. return counter;
  1767. }
  1768. BOOL NavItemI_IsExpanded(HNAVITEM hItem)
  1769. {
  1770. return (hItem && (TVIS_EXPANDED == (TVIS_EXPANDED & (UINT)SendMessageW(((NAVITM*)hItem)->hwndTree, TVM_GETITEMSTATE,
  1771. (WPARAM)((NAVITM*)hItem)->hTreeItem, (LPARAM)TVIS_EXPANDED))));
  1772. }
  1773. INT NavItemI_GetImageIndex(HNAVITEM hItem, INT imageType)
  1774. {
  1775. NAVITM *item;
  1776. item = (NAVITM*)hItem;
  1777. if (NULL == item)
  1778. return -1;
  1779. if (0 != (NIS_DEFAULTIMAGE & item->style))
  1780. return -1;
  1781. switch(imageType)
  1782. {
  1783. case IMAGE_NORMAL_I: return ((NAVITM*)hItem)->iImage;
  1784. case IMAGE_SELECTED_I: return ((NAVITM*)hItem)->iSelectedImage;
  1785. }
  1786. return -1;
  1787. }
  1788. BOOL NavItemI_GetIndirect(HNAVITEM hItem, NAVITEM_I *pnis)
  1789. {
  1790. NAVITM *pItem;
  1791. if (!hItem || !pnis) return FALSE;
  1792. pItem = (NAVITM*)hItem;
  1793. if (NIMF_ITEMID_I & pnis->mask) pnis->id = pItem->id;
  1794. if (NIMF_IMAGE_I & pnis->mask) pnis->iImage = pItem->iImage;
  1795. if (NIMF_IMAGESEL_I & pnis->mask) pnis->iSelectedImage = pItem->iSelectedImage;
  1796. if (NIMF_STYLE_I & pnis->mask) pnis->style = (pnis->styleMask & pItem->style);
  1797. if (NIMF_TEXT_I & pnis->mask && !NavItemI_GetText(pItem, pnis->pszText, pnis->cchTextMax)) return FALSE;
  1798. if (NIMF_TEXTINVARIANT_I & pnis->mask && !NavItemI_GetInvariantText(pItem, pnis->pszInvariant, pnis->cchInvariantMax)) return FALSE;
  1799. if (NIMF_STATE_I & pnis->mask) pnis->state = NavItemI_GetState(pItem, 0xFFFFFFFF);
  1800. if (NIMF_FONT_I & pnis->mask) pnis->hFont = NavItemI_GetFont(pItem);
  1801. if (NIMF_PARAM_I & pnis->mask) pnis->lParam = pItem->lParam;
  1802. return TRUE;
  1803. }
  1804. BOOL NavItemI_GetText(HNAVITEM hItem, LPWSTR pszText, INT cchMaxLen)
  1805. {
  1806. if (!hItem || !pszText) return FALSE;
  1807. return (S_OK == StringCchCopyW(pszText, cchMaxLen, (((NAVITM*)hItem)->pszText) ? ((NAVITM*)hItem)->pszText : L""));
  1808. }
  1809. BOOL NavItemI_GetInvariantText(HNAVITEM hItem, LPWSTR pszText, INT cchMaxLen)
  1810. {
  1811. if (!hItem || !pszText) return FALSE;
  1812. return (S_OK == StringCchCopyW(pszText, cchMaxLen, (((NAVITM*)hItem)->pszInvariant) ? ((NAVITM*)hItem)->pszInvariant : L""));
  1813. }
  1814. BOOL NavItemI_HasChildren(HNAVITEM hItem)
  1815. {
  1816. return (hItem && (0 != (NIS_HASCHILDREN_I & ((NAVITM*)hItem)->style)));
  1817. }
  1818. BOOL NavItemI_HasChildrenReal(HNAVITEM hItem)
  1819. {
  1820. return (hItem && SendMessageW(((NAVITM*)hItem)->hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_CHILD, (LPARAM)((NAVITM*)hItem)->hTreeItem));
  1821. }
  1822. BOOL NavItemI_IsSelected(HNAVITEM hItem)
  1823. {
  1824. return (NIS_SELECTED_I == NavItemI_GetState(hItem, NIS_SELECTED_I));
  1825. }
  1826. BOOL NavItemI_SetId(HNAVITEM hItem, INT itemId)
  1827. {
  1828. if (!hItem || itemId < 0) return FALSE;
  1829. if (((NAVITM*)hItem)->id == itemId) return TRUE;
  1830. if (FindNavItemByNavIdEx(((NAVITM*)hItem)->hwndTree, itemId, TVI_ROOT)) return FALSE;
  1831. ((NAVITM*)hItem)->id = itemId;
  1832. return TRUE;
  1833. }
  1834. BOOL NavItemI_SetImageIndex(HNAVITEM hItem, INT mlilIndex, INT imageType)
  1835. {
  1836. if (!hItem) return FALSE;
  1837. switch(imageType)
  1838. {
  1839. case IMAGE_NORMAL_I: ((NAVITM*)hItem)->iImage = mlilIndex; break;
  1840. case IMAGE_SELECTED_I: ((NAVITM*)hItem)->iSelectedImage = mlilIndex; break;
  1841. default: return FALSE;
  1842. }
  1843. NavItemI_Invalidate(hItem, NULL, FALSE);
  1844. return TRUE;
  1845. }
  1846. BOOL NavItemI_SetStyle(HNAVITEM hItem, UINT style, UINT mask)
  1847. {
  1848. UINT newStyle;
  1849. if (!hItem) return FALSE;
  1850. newStyle = (((NAVITM*)hItem)->style & ~mask) | style;
  1851. if (((NAVITM*)hItem)->style != newStyle)
  1852. {
  1853. ((NAVITM*)hItem)->style = newStyle;
  1854. NavItemI_Invalidate(hItem, NULL, FALSE);
  1855. }
  1856. return TRUE;
  1857. }
  1858. BOOL NavItemI_SetText(HNAVITEM hItem, LPCWSTR pszText)
  1859. {
  1860. if (!hItem) return FALSE;
  1861. if (!pszText)
  1862. {
  1863. free(((NAVITM*)hItem)->pszText);
  1864. ((NAVITM*)hItem)->pszText = NULL;
  1865. ((NAVITM*)hItem)->cchTextMax = 0;
  1866. }
  1867. else
  1868. {
  1869. INT len = lstrlenW(pszText);
  1870. if (len >= ((NAVITM*)hItem)->cchTextMax)
  1871. {
  1872. LPVOID data;
  1873. data = realloc(((NAVITM*)hItem)->pszText, sizeof(WCHAR)*(len + 4));
  1874. if (!data) return FALSE;
  1875. ((NAVITM*)hItem)->pszText = (LPWSTR)data;
  1876. ((NAVITM*)hItem)->cchTextMax = len + 4;
  1877. }
  1878. if (S_OK != StringCchCopyW(((NAVITM*)hItem)->pszText, ((NAVITM*)hItem)->cchTextMax, pszText)) return FALSE;
  1879. }
  1880. NavItemI_Invalidate(hItem, NULL, FALSE);
  1881. return TRUE;
  1882. }
  1883. BOOL NavItemI_SetInvariantText(HNAVITEM hItem, LPCWSTR pszText)
  1884. {
  1885. if (!hItem) return FALSE;
  1886. if (!pszText)
  1887. {
  1888. free(((NAVITM*)hItem)->pszInvariant);
  1889. ((NAVITM*)hItem)->pszInvariant = NULL;
  1890. ((NAVITM*)hItem)->cchInvariantMax = 0;
  1891. }
  1892. else
  1893. {
  1894. INT len = lstrlenW(pszText);
  1895. if (len >= ((NAVITM*)hItem)->cchInvariantMax)
  1896. {
  1897. LPVOID data;
  1898. data = realloc(((NAVITM*)hItem)->pszInvariant, sizeof(WCHAR)*(len + 4));
  1899. if (!data) return FALSE;
  1900. ((NAVITM*)hItem)->pszInvariant = (LPWSTR)data;
  1901. ((NAVITM*)hItem)->cchInvariantMax = len + 4;
  1902. }
  1903. if (S_OK != StringCchCopyW(((NAVITM*)hItem)->pszInvariant, ((NAVITM*)hItem)->cchInvariantMax, pszText)) return FALSE;
  1904. }
  1905. return TRUE;
  1906. }
  1907. BOOL NavItemI_SetState(HNAVITEM hItem, UINT state, UINT stateMask)
  1908. {
  1909. TVITEMW item;
  1910. if (!hItem) return FALSE;
  1911. item.hItem = ((NAVITM*)hItem)->hTreeItem;
  1912. item.mask = TVIF_STATE;
  1913. item.state = 0;
  1914. item.stateMask = 0;
  1915. switch(state)
  1916. {
  1917. case NIS_SELECTED_I: item.state |= TVIS_SELECTED; break;
  1918. case NIS_EXPANDED_I: item.state |= TVIS_EXPANDED; break;
  1919. case NIS_DROPHILITED_I: item.state |= TVIS_DROPHILITED; break;
  1920. }
  1921. switch(stateMask)
  1922. {
  1923. case NIS_SELECTED_I: item.stateMask |= TVIS_SELECTED; break;
  1924. case NIS_EXPANDED_I: item.stateMask |= TVIS_EXPANDED; break;
  1925. case NIS_DROPHILITED_I: item.stateMask |= TVIS_DROPHILITED; break;
  1926. }
  1927. return (BOOL)SendMessageW(((NAVITM*)hItem)->hwndTree, TVM_SETITEMW, (WPARAM)0, (LPARAM)&item);
  1928. }
  1929. UINT NavItemI_GetState(HNAVITEM hItem, UINT stateMask)
  1930. {
  1931. UINT treeState, navState;
  1932. if (!hItem) return 0;
  1933. treeState = (UINT)SendMessageW(((NAVITM*)hItem)->hwndTree, TVM_GETITEMSTATE, (WPARAM)((NAVITM*)hItem)->hTreeItem, (LPARAM)0xFFFFFFFF);
  1934. navState = 0;
  1935. if (TVIS_SELECTED & treeState) navState |= NIS_SELECTED_I;
  1936. if (TVIS_EXPANDED & treeState) navState |= NIS_EXPANDED_I;
  1937. if (TVIS_DROPHILITED & treeState) navState |= NIS_DROPHILITED_I;
  1938. return (navState & stateMask);
  1939. }
  1940. UINT NavItemI_GetStyle(HNAVITEM hItem, UINT styleMask)
  1941. {
  1942. return (hItem) ? (((NAVITM*)hItem)->style & styleMask) : 0;
  1943. }
  1944. BOOL NavItemI_SetIndirect(HNAVITEM hItem, NAVITEM_I *pnis)
  1945. {
  1946. if (!hItem || !pnis) return FALSE;
  1947. BOOL fResult = TRUE;
  1948. ((NAVITM*)hItem)->fBlockInvalid = TRUE;
  1949. if (NIMF_ITEMID_I & pnis->mask && !NavItemI_SetId(hItem, pnis->id)) fResult = FALSE;
  1950. if (NIMF_IMAGE_I & pnis->mask && !NavItemI_SetImageIndex(hItem, pnis->iImage, IMAGE_NORMAL_I)) fResult = FALSE;
  1951. if (NIMF_IMAGESEL_I & pnis->mask && !NavItemI_SetImageIndex(hItem, pnis->iSelectedImage, IMAGE_SELECTED_I)) fResult = FALSE;
  1952. if (NIMF_STYLE_I & pnis->mask && !NavItemI_SetStyle(hItem, pnis->style, pnis->styleMask)) fResult = FALSE;
  1953. if (NIMF_TEXT_I & pnis->mask && !NavItemI_SetText(hItem, pnis->pszText)) fResult = FALSE;
  1954. if (NIMF_TEXTINVARIANT_I & pnis->mask && !NavItemI_SetText(hItem, pnis->pszInvariant)) fResult = FALSE;
  1955. if (NIMF_STATE_I & pnis->mask && !NavItemI_SetState(hItem, pnis->state, pnis->stateMask)) fResult = FALSE;
  1956. if (NIMF_FONT_I & pnis->mask && !NavItemI_SetFont(hItem, pnis->hFont)) fResult = FALSE;
  1957. if (NIMF_PARAM_I & pnis->mask) ((NAVITM*)hItem)->lParam = pnis->lParam;
  1958. ((NAVITM*)hItem)->fBlockInvalid = FALSE;
  1959. if (!NavItemI_Invalidate(hItem, NULL, FALSE)) fResult = FALSE;
  1960. return fResult;
  1961. }
  1962. BOOL NavItemI_GetRect(HNAVITEM hItem, RECT *prc, BOOL fItemRect)
  1963. {
  1964. if (!hItem || !prc) return FALSE;
  1965. *((HTREEITEM*)prc) = ((NAVITM*)hItem)->hTreeItem;
  1966. return (BOOL)SendMessageW(((NAVITM*)hItem)->hwndTree, TVM_GETITEMRECT, (WPARAM)fItemRect, (LPARAM)prc);
  1967. }
  1968. BOOL NavItemI_Invalidate(HNAVITEM hItem, RECT *prc, BOOL fErase)
  1969. {
  1970. if (!hItem) return FALSE;
  1971. if (!((NAVITM*)hItem)->fBlockInvalid)
  1972. {
  1973. RECT rc;
  1974. if (NavItemI_GetRect(hItem, &rc, FALSE))
  1975. {
  1976. if (prc) IntersectRect(&rc, &rc, prc);
  1977. InvalidateRect(((NAVITM*)hItem)->hwndTree, &rc, fErase);
  1978. return TRUE;
  1979. }
  1980. }
  1981. return TRUE;
  1982. }
  1983. BOOL NavItemI_Expand(HNAVITEM hItem, UINT flag)
  1984. {
  1985. UINT tiFlag;
  1986. if (!hItem) return FALSE;
  1987. switch(flag)
  1988. {
  1989. case NAVITEM_TOGGLE_I: tiFlag = TVE_TOGGLE; break;
  1990. case NAVITEM_EXPAND_I: tiFlag = TVE_EXPAND; break;
  1991. case NAVITEM_COLLAPSE_I: tiFlag = TVE_COLLAPSE; break;
  1992. default: return FALSE;
  1993. }
  1994. return (BOOL)SendMessageW(((NAVITM*)hItem)->hwndTree, TVM_EXPAND, (WPARAM)tiFlag, (LPARAM)((NAVITM*)hItem)->hTreeItem);
  1995. }
  1996. INT NavItemI_GetFullName(HNAVITEM hItem, LPWSTR pszFullName, INT cchMaxLen)
  1997. {
  1998. wchar_t *current, *scanner, *text;
  1999. INT remaining;
  2000. if (!pszFullName || !hItem) return 0;
  2001. pszFullName[0] = 0x00;
  2002. remaining = cchMaxLen;
  2003. current = pszFullName;
  2004. while(hItem && remaining)
  2005. {
  2006. text = (((NAVITM*)hItem)->pszInvariant) ? ((NAVITM*)hItem)->pszInvariant : ((NAVITM*)hItem)->pszText;
  2007. if (!text) text = EMPTY_ITEM_NAME;
  2008. if (current != pszFullName)
  2009. {
  2010. *current = SEPARATOR;
  2011. current++;
  2012. remaining--;
  2013. }
  2014. scanner = text + lstrlenW(text) - 1;
  2015. BOOL second = FALSE;
  2016. while (scanner >= text && remaining)
  2017. {
  2018. *current = *scanner;
  2019. current++;
  2020. remaining--;
  2021. if (SEPARATOR == *scanner && !second) { second = TRUE; continue; }
  2022. second = FALSE;
  2023. scanner--;
  2024. }
  2025. hItem = NavItemI_GetParent(hItem);
  2026. }
  2027. if (remaining)
  2028. {
  2029. *current = 0x00;
  2030. current--;
  2031. scanner = pszFullName;
  2032. while (scanner < current)
  2033. {
  2034. wchar_t tmp = *scanner;
  2035. *scanner = *current;
  2036. *current = tmp;
  2037. scanner++;
  2038. current--;
  2039. }
  2040. }
  2041. else
  2042. {
  2043. *pszFullName = 0x00;
  2044. return 0;
  2045. }
  2046. return cchMaxLen - remaining;
  2047. }
  2048. BOOL NavItemI_Move(HNAVITEM hItem, HNAVITEM hItemDest, BOOL fAfter)
  2049. {
  2050. WORD order;
  2051. UINT flags;
  2052. HNAVCTRL hNav;
  2053. if (!hItem) return FALSE;
  2054. if (hItemDest)
  2055. {
  2056. order = ((NAVITM*)hItemDest)->sortOrder;
  2057. flags = (fAfter) ? NOF_MOVEONEAFTER_I : NOF_MOVEONEBEFORE_I;
  2058. }
  2059. else
  2060. {
  2061. order = 1;
  2062. flags = NOF_MOVEONEBEFORE_I;
  2063. }
  2064. hNav = (HNAVCTRL)GetPropW(((NAVITM*)hItem)->hwndTree, NAVMGR_HWNDPROPW);
  2065. NavCtrlI_BeginUpdate(hNav, NUF_LOCK_NONE_I);
  2066. order = NavItemI_SetOrder(hItem, order, flags);
  2067. NavItemI_EnsureVisible(hItem);
  2068. NavCtrlI_EndUpdate(hNav);
  2069. return ((WORD)-1 != order);
  2070. }
  2071. static INT CALLBACK CommpareByOrderCB(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  2072. {
  2073. if (lParam1 == lParam2) return 0;
  2074. if (NULL == lParam1) return 1;
  2075. return (((NAVITM*)lParam1)->sortOrder - ((NAVITM*)lParam2)->sortOrder);
  2076. }
  2077. static BOOL NavItemI_SetOrderWorker(HNAVITEM hItem, HTREEITEM hTreeFirst, WORD order, UINT flags)
  2078. {
  2079. bool bRecurse;
  2080. if (!hItem) return FALSE;
  2081. bRecurse = false;
  2082. if (0 == order)
  2083. {
  2084. order = 1;
  2085. flags = NOF_MOVEONEBEFORE_I;
  2086. }
  2087. if (((WORD)-1) == order || ((NAVITM*)hItem)->sortOrder != order)
  2088. {
  2089. TVITEMW treeItem; // keep it here so it will be released prior to recurtion
  2090. ((NAVITM*)hItem)->sortOrder = (((WORD)-1) == order) ? 1 : order;
  2091. treeItem.mask = TVIF_HANDLE | TVIF_PARAM;
  2092. treeItem.hItem = hTreeFirst;
  2093. while (treeItem.hItem)
  2094. {
  2095. if (treeItem.hItem != ((NAVITM*)hItem)->hTreeItem)
  2096. {
  2097. if (!SendMessageW(((NAVITM*)hItem)->hwndTree, TVM_GETITEMW, (WPARAM)0, (LPARAM)&treeItem)) return FALSE;
  2098. if (((WORD)-1) == order)
  2099. {
  2100. if (treeItem.lParam && ((NAVITM*)hItem)->sortOrder <= ((NAVITM*)treeItem.lParam)->sortOrder)
  2101. ((NAVITM*)hItem)->sortOrder = ((NAVITM*)treeItem.lParam)->sortOrder + 1;
  2102. }
  2103. else
  2104. {
  2105. if (treeItem.lParam && ((NAVITM*)treeItem.lParam)->sortOrder == order)
  2106. {
  2107. switch(flags)
  2108. {
  2109. case NOF_MOVEONEBEFORE_I:
  2110. hItem = (HNAVITEM)treeItem.lParam;
  2111. order = ((NAVITM*)hItem)->sortOrder + 1;
  2112. break;
  2113. case NOF_MOVEONEAFTER_I:
  2114. order++;
  2115. flags = NOF_MOVEONEBEFORE_I;
  2116. break;
  2117. case NOF_MOVEBEFORE_I:
  2118. if (1 == order)
  2119. {
  2120. hItem = (HNAVITEM)treeItem.lParam;
  2121. order = ((NAVITM*)hItem)->sortOrder + 1;
  2122. flags = NOF_MOVEONEBEFORE_I;
  2123. }
  2124. else order--;
  2125. break;
  2126. case NOF_MOVEAFTER_I:
  2127. order++;
  2128. break;
  2129. default: return FALSE;
  2130. }
  2131. bRecurse = true;
  2132. break;
  2133. }
  2134. }
  2135. }
  2136. treeItem.hItem = (HTREEITEM)SendMessageW(((NAVITM*)hItem)->hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_NEXT, (LPARAM)treeItem.hItem);
  2137. }
  2138. }
  2139. return (bRecurse) ? NavItemI_SetOrderWorker(hItem, hTreeFirst, order, flags) : TRUE;
  2140. }
  2141. WORD NavItemI_SetOrder(HNAVITEM hItem, WORD order, UINT flags)
  2142. {
  2143. HTREEITEM hTreeParent;
  2144. if (!hItem) return (WORD)-1;
  2145. hTreeParent = (HTREEITEM)SendMessageW(((NAVITM*)hItem)->hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_PARENT, (LPARAM)((NAVITM*)hItem)->hTreeItem);
  2146. if (NavItemI_SetOrderWorker(hItem,
  2147. (HTREEITEM)SendMessageW(((NAVITM*)hItem)->hwndTree, TVM_GETNEXTITEM,
  2148. (WPARAM)((hTreeParent) ? TVGN_CHILD : TVGN_ROOT), (LPARAM)hTreeParent),
  2149. order, flags))
  2150. {
  2151. HNAVCTRL hNav;
  2152. TVSORTCB sort;
  2153. sort.hParent = hTreeParent;
  2154. sort.lpfnCompare = CommpareByOrderCB;
  2155. sort.lParam = 0;
  2156. hNav = (HNAVCTRL)GetPropW(((NAVITM*)hItem)->hwndTree, NAVMGR_HWNDPROPW);
  2157. NavCtrlI_BeginUpdate(hNav, NUF_LOCK_NONE_I);
  2158. SendMessageW(((NAVITM*)hItem)->hwndTree, TVM_SORTCHILDRENCB, (WPARAM)FALSE, (LPARAM)&sort);
  2159. NavCtrlI_EndUpdate(hNav);
  2160. }
  2161. return ((NAVITM*)hItem)->sortOrder;
  2162. }
  2163. WORD NavItemI_GetOrder(HNAVITEM hItem)
  2164. {
  2165. return (hItem) ? ((NAVITM*)hItem)->sortOrder : 0xFFFF;
  2166. }
  2167. BOOL NavItemI_Select(HNAVITEM hItem)
  2168. {
  2169. BOOL fResult;
  2170. if (!hItem) return FALSE;
  2171. fResult = (BOOL)SendMessageW(((NAVITM*)hItem)->hwndTree, TVM_SELECTITEM, (WPARAM)TVGN_CARET, (LPARAM)((NAVITM*)hItem)->hTreeItem);
  2172. SendMessageW(((NAVITM*)hItem)->hwndTree, WM_HSCROLL, MAKEWPARAM(SB_LEFT, 0), NULL);
  2173. SendMessageW(((NAVITM*)hItem)->hwndTree, WM_HSCROLL, MAKEWPARAM(SB_ENDSCROLL, 0), NULL);
  2174. return fResult;
  2175. }
  2176. BOOL NavItemI_EnsureVisible(HNAVITEM hItem)
  2177. {
  2178. BOOL fResult;
  2179. if (!hItem) return FALSE;
  2180. fResult = (BOOL)SendMessageW(((NAVITM*)hItem)->hwndTree, TVM_ENSUREVISIBLE, (WPARAM)0, (LPARAM)((NAVITM*)hItem)->hTreeItem);
  2181. if (fResult)
  2182. {
  2183. SCROLLINFO si;
  2184. si.cbSize = sizeof(SCROLLINFO);
  2185. si.fMask = SIF_POS | SIF_RANGE;
  2186. if(GetScrollInfo(((NAVITM*)hItem)->hwndTree, SB_HORZ, &si) && (si.nMin != si.nPos))
  2187. {
  2188. SendMessageW(((NAVITM*)hItem)->hwndTree, WM_HSCROLL, MAKEWPARAM(SB_LEFT, 0), NULL);
  2189. SendMessageW(((NAVITM*)hItem)->hwndTree, WM_HSCROLL, MAKEWPARAM(SB_ENDSCROLL, 0), NULL);
  2190. }
  2191. }
  2192. return fResult;
  2193. }
  2194. HFONT NavItemI_GetFont(HNAVITEM hItem)
  2195. {
  2196. return (hItem) ? ((NAVITM*)hItem)->hFont : NULL;
  2197. }
  2198. HFONT NavItemI_SetFont(HNAVITEM hItem, HFONT hFont)
  2199. {
  2200. HFONT hFontOld;
  2201. if (!hItem) return NULL;
  2202. hFontOld = ((NAVITM*)hItem)->hFont;
  2203. ((NAVITM*)hItem)->hFont = hFont;
  2204. NavItemI_Invalidate(hItem, NULL, FALSE);
  2205. return hFontOld;
  2206. }
  2207. HIMAGELIST NavItemI_CreateDragImage(HNAVITEM hItem, LPCWSTR pszTipText)
  2208. {
  2209. HIMAGELIST hIL;
  2210. HNAVCTRL hNav;
  2211. HBITMAP hbmp;
  2212. INT cy, cx, ilIndex;
  2213. RECT rcImage, rcText, rcTip;
  2214. HDC hdcMem, hdcScreen;
  2215. HFONT hFont, hFontOld, hFontTip;
  2216. BOOL fDestroyFont;
  2217. fDestroyFont = FALSE;
  2218. hFont = NULL;
  2219. hFontTip = NULL;
  2220. if (!hItem) return NULL;
  2221. hNav = (HNAVCTRL)GetPropW(((NAVITM*)hItem)->hwndTree, NAVMGR_HWNDPROPW);
  2222. if (!hNav) return NULL;
  2223. cx = DRAGIMAGE_OFFSET_X;
  2224. cy = (INT)SendMessageW(((NAVITM*)hItem)->hwndTree, TVM_GETITEMHEIGHT, (WPARAM)0, (LPARAM)0L) + 2*DRAGIMAGE_OFFSET_Y;
  2225. if (!cy) return NULL;
  2226. hdcScreen = GetDCEx(((NAVITM*)hItem)->hwndTree, NULL, DCX_WINDOW | DCX_CACHE);
  2227. hdcMem = (hdcScreen) ? CreateCompatibleDC(NULL) : NULL;
  2228. if (!hdcMem)
  2229. {
  2230. if (hdcScreen) ReleaseDC(((NAVITM*)hItem)->hwndTree, hdcScreen);
  2231. return NULL;
  2232. }
  2233. SetRect(&rcText, 0,0,0,0);
  2234. SetRect(&rcTip, 0,0,0,0);
  2235. if (((NAVITM*)hItem)->pszText)
  2236. {
  2237. if (((NAVITM*)hItem)->hFont) hFont = ((NAVITM*)hItem)->hFont;
  2238. else
  2239. {
  2240. hFont = (HFONT)::SendMessageW(((NAVITM*)hItem)->hwndTree, WM_GETFONT, 0, 0);
  2241. if (NULL == hFont)
  2242. hFont = (HFONT)MlStockObjects_Get(DEFAULT_FONT);
  2243. if ((NIS_BOLD_I | NIS_ITALIC_I | NIS_UNDERLINE_I) & ((NAVITM*)hItem)->style)
  2244. {
  2245. LOGFONTW lf = { 0 };
  2246. GetObjectW(hFont, sizeof(LOGFONTW), &lf);
  2247. if (NIS_BOLD_I & ((NAVITM*)hItem)->style) lf.lfWeight = FW_BOLD;
  2248. if (NIS_ITALIC_I & ((NAVITM*)hItem)->style) lf.lfItalic = TRUE;
  2249. if (NIS_UNDERLINE_I & ((NAVITM*)hItem)->style) lf.lfUnderline = TRUE;
  2250. hFont = CreateFontIndirectW(&lf);
  2251. fDestroyFont = TRUE;
  2252. }
  2253. }
  2254. if (hFont) hFontOld = (HFONT)SelectObject(hdcMem, hFont);
  2255. DrawTextW(hdcMem, ((NAVITM*)hItem)->pszText, -1, &rcText, DT_CALCRECT | DT_NOPREFIX);
  2256. if(rcText.bottom - rcText.top > cy) cy = (rcText.bottom - rcText.top) + 2;
  2257. cx += ((rcText.right - rcText.left) + DRAGIMAGE_OFFSET_X);
  2258. }
  2259. ilIndex = -1;
  2260. if (((NAVMNGR*)hNav)->hmlilImages)
  2261. {
  2262. hIL = (HIMAGELIST)SendMessageW(((NAVMNGR*)hNav)->hwndHost, TVM_GETIMAGELIST, (WPARAM)TVSIL_NORMAL, (LPARAM)0);
  2263. if (hIL && MLImageListI_GetRealList(((NAVMNGR*)hNav)->hmlilImages) == hIL)
  2264. {
  2265. COLORREF rgbBk, rgbFg;
  2266. GetItemColors(hNav, NIS_SELECTED_I | NIS_FOCUSED_I, &rgbBk, &rgbFg);
  2267. ilIndex = GetRealImageIndex(hNav, (NAVITM*)hItem, IMAGE_SELECTED_I, rgbBk, rgbFg);
  2268. }
  2269. }
  2270. else
  2271. hIL = NULL;
  2272. if (-1 != ilIndex && NULL != hIL)
  2273. {
  2274. IMAGEINFO ii;
  2275. ImageList_GetImageInfo(hIL, ilIndex, &ii);
  2276. cx += (ii.rcImage.right - ii.rcImage.left) + 5;
  2277. SetRect(&rcImage, 0, 0, ii.rcImage.right - ii.rcImage.left, ii.rcImage.bottom - ii.rcImage.top);
  2278. }
  2279. else SetRect(&rcImage, 0,0,0,0);
  2280. OffsetRect(&rcImage, DRAGIMAGE_OFFSET_X, ((cy - DRAGIMAGE_OFFSET_Y) - (rcImage.bottom - rcImage.top))/2);
  2281. OffsetRect(&rcText, rcImage.right + ((rcImage.right != rcImage.left) ? 5 : 0), ((cy - DRAGIMAGE_OFFSET_Y) - (rcText.bottom - rcText.top))/2);
  2282. if (pszTipText && *pszTipText)
  2283. {
  2284. HFONT hFontTmp;
  2285. hFontTip = (HFONT)::SendMessageW(((NAVITM*)hItem)->hwndTree, WM_GETFONT, 0, 0);
  2286. if (!hFontTip) hFontTip = (HFONT)MlStockObjects_Get(DEFAULT_FONT);
  2287. hFontTmp = (HFONT)SelectObject(hdcMem, hFontTip);
  2288. DrawTextW(hdcMem, pszTipText, -1, &rcTip, DT_CALCRECT | DT_NOPREFIX);
  2289. SelectObject(hdcMem, hFontTmp);
  2290. if (rcTip.right - rcTip.left > (cx - rcText.left + 3)) cx = rcText.left + (rcTip.right - rcTip.left) + 3;
  2291. OffsetRect(&rcTip, rcText.left, cy + 1);
  2292. cy += ((rcTip.bottom - rcTip.top) + 3);
  2293. }
  2294. hbmp = (3 != cx) ? CreateCompatibleBitmap(hdcScreen, cx, cy) : NULL;
  2295. if (hbmp)
  2296. {
  2297. HGDIOBJ hgdiOld;
  2298. RECT rc;
  2299. hgdiOld = SelectObject(hdcMem, hbmp);
  2300. SetBkColor(hdcMem, WADlg_getColor(WADLG_SELBAR_BGCOLOR));
  2301. SetTextColor(hdcMem, WADlg_getColor(WADLG_SELBAR_FGCOLOR));
  2302. SetRect(&rc, 0, 0, cx, cy);
  2303. ExtTextOutW(hdcMem, 0, 0, ETO_OPAQUE, &rc, L"", 0, 0);
  2304. if (hIL && -1 != ilIndex)
  2305. {
  2306. ImageList_DrawEx(hIL, ilIndex, hdcMem, rcImage.left, rcImage.top,
  2307. (rcImage.right - rcImage.left), (rcImage.bottom - rcImage.top), CLR_DEFAULT, CLR_DEFAULT, ILD_NORMAL);
  2308. }
  2309. if (((NAVITM*)hItem)->pszText) DrawTextW(hdcMem, ((NAVITM*)hItem)->pszText, -1, &rcText, DT_NOPREFIX);
  2310. if (pszTipText && *pszTipText)
  2311. {
  2312. HFONT hFontTmp;
  2313. hFontTmp = (HFONT)SelectObject(hdcMem, hFontTip);
  2314. DrawTextW(hdcMem, pszTipText, -1, &rcTip, DT_NOPREFIX);
  2315. SelectObject(hdcMem, hFontTmp);
  2316. }
  2317. SelectObject(hdcMem, hgdiOld);
  2318. hIL = ImageList_Create(cx, cy, ILC_COLOR24 | ILC_MASK, 0, 1);
  2319. if (hIL && -1 == ImageList_Add(hIL, hbmp, NULL))
  2320. {
  2321. ImageList_Destroy(hIL);
  2322. hIL = NULL;
  2323. }
  2324. DeleteObject(hbmp);
  2325. }
  2326. if (hFont)
  2327. {
  2328. SelectObject(hdcMem, hFontOld);
  2329. if (fDestroyFont) DeleteObject(hFont);
  2330. }
  2331. // if (hFontTip) DeleteObject(hFontTip); // we not creating it...
  2332. DeleteDC(hdcMem);
  2333. ReleaseDC(((NAVITM*)hItem)->hwndTree, hdcScreen);
  2334. return hIL;
  2335. }