widgetHost.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. #include "main.h"
  2. #include "./widgetHost.h"
  3. #define WIDGETHOST_WINDOW_CLASS L"NullsoftDevicesWidgetHost"
  4. #define WIDGETHOST_WIDGET_ID 1000
  5. typedef
  6. enum WidgetHostState
  7. {
  8. WIDGETHOST_STATE_FROZEN_UI = (1 << 0),
  9. } WidgetHostState;
  10. DEFINE_ENUM_FLAG_OPERATORS(WidgetHostState);
  11. typedef struct WidgetHost
  12. {
  13. WidgetHostState state;
  14. WidgetStyle widgetStyle;
  15. HFONT font;
  16. HRGN updateRegion;
  17. POINT updateOffset;
  18. } WidgetHost;
  19. typedef struct WidgetHostCreateParam
  20. {
  21. WidgetCreateProc widgetCreate;
  22. void *widgetCreateParam;
  23. } WidgetHostCreateParam;
  24. #define WIDGETHOST(_hwnd) ((WidgetHost*)(LONGX86)GetWindowLongPtrW((_hwnd), 0))
  25. #define WIDGETHOST_RET_VOID(_self, _hwnd) {(_self) = WIDGETHOST((_hwnd)); if (NULL == (_self)) return;}
  26. #define WIDGETHOST_RET_VAL(_self, _hwnd, _error) {(_self) = WIDGETHOST((_hwnd)); if (NULL == (_self)) return (_error);}
  27. #define WIDGETHOST_WIDGET(_hostWindow) (GetDlgItem((_hostWindow), WIDGETHOST_WIDGET_ID))
  28. #define WIDGETHOST_IS_FROZEN(_self) (0 != (WIDGETHOST_STATE_FROZEN_UI & (_self)->state))
  29. #define WIDGETHOST_FREEZE(_self) (((_self)->state) |= WIDGETHOST_STATE_FROZEN_UI)
  30. #define WIDGETHOST_THAW(_self) (((_self)->state) &= ~WIDGETHOST_STATE_FROZEN_UI)
  31. static LRESULT CALLBACK
  32. WidgetHost_WindowProc(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam);
  33. static ATOM
  34. WidgetHost_GetClassAtom(HINSTANCE instance)
  35. {
  36. WNDCLASSEXW klass;
  37. ATOM klassAtom;
  38. klassAtom = (ATOM)GetClassInfoExW(instance, WIDGETHOST_WINDOW_CLASS, &klass);
  39. if (0 != klassAtom)
  40. return klassAtom;
  41. memset(&klass, 0, sizeof(klass));
  42. klass.cbSize = sizeof(klass);
  43. klass.style = CS_DBLCLKS;
  44. klass.lpfnWndProc = WidgetHost_WindowProc;
  45. klass.cbClsExtra = 0;
  46. klass.cbWndExtra = sizeof(WidgetHost*);
  47. klass.hInstance = instance;
  48. klass.hIcon = NULL;
  49. klass.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
  50. klass.hbrBackground = NULL;
  51. klass.lpszMenuName = NULL;
  52. klass.lpszClassName = WIDGETHOST_WINDOW_CLASS;
  53. klass.hIconSm = NULL;
  54. klassAtom = RegisterClassExW(&klass);
  55. return klassAtom;
  56. }
  57. HWND
  58. WidgetHost_Create(unsigned int windowStyle, int x, int y, int width, int height,
  59. HWND parentWindow, WidgetCreateProc createProc, void *createParam)
  60. {
  61. HINSTANCE instance;
  62. ATOM klassAtom;
  63. HWND hwnd;
  64. WidgetHostCreateParam hostParam;
  65. if (NULL == createProc)
  66. return NULL;
  67. instance = GetModuleHandleW(NULL);
  68. klassAtom = WidgetHost_GetClassAtom(instance);
  69. if (0 == klassAtom)
  70. return NULL;
  71. hostParam.widgetCreate = createProc;
  72. hostParam.widgetCreateParam = createParam;
  73. hwnd = CreateWindowExW(WS_EX_NOPARENTNOTIFY |WS_EX_CONTROLPARENT,
  74. (LPCWSTR)MAKEINTATOM(klassAtom), NULL,
  75. WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | windowStyle,
  76. x, y, width, height,
  77. parentWindow, NULL, instance, &hostParam);
  78. return hwnd;
  79. }
  80. static void
  81. WidgetHost_Layout(HWND hwnd, BOOL redraw)
  82. {
  83. WidgetHost *self;
  84. RECT rect;
  85. WIDGETHOST_RET_VOID(self, hwnd);
  86. if (FALSE == GetClientRect(hwnd, &rect))
  87. return;
  88. HWND widgetWindow = WIDGETHOST_WIDGET(hwnd);
  89. if (NULL != widgetWindow)
  90. {
  91. unsigned int flags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER;
  92. if (FALSE == redraw)
  93. flags |= SWP_NOREDRAW;
  94. SetWindowPos(widgetWindow, NULL, 0, 0, RECTWIDTH(rect), RECTHEIGHT(rect), flags);
  95. }
  96. }
  97. static void
  98. WidgetHost_Paint(HWND hwnd, HDC hdc, const RECT *paintRect, BOOL erase)
  99. {
  100. if (FALSE != erase)
  101. {
  102. COLORREF backColor, prevBackColor;
  103. backColor = Graphics_GetSkinColor(WADLG_WNDBG);
  104. prevBackColor = SetBkColor(hdc, backColor);
  105. ExtTextOut(hdc, 0, 0, ETO_OPAQUE, paintRect, NULL, 0, NULL);
  106. SetBkColor(hdc, prevBackColor);
  107. }
  108. }
  109. static void
  110. WidgetHost_UpdateSkin(HWND hwnd)
  111. {
  112. WidgetHost *self;
  113. WIDGETHOST_RET_VOID(self, hwnd);
  114. BOOL styleChanged = FALSE;
  115. if (FALSE != WidgetStyle_UpdateDefaultColors(&self->widgetStyle))
  116. styleChanged = TRUE;
  117. if (FALSE != styleChanged)
  118. {
  119. HWND widgetWindow = WIDGETHOST_WIDGET(hwnd);
  120. if (NULL != widgetWindow)
  121. {
  122. WIDGET_STYLE_COLOR_CHANGED(widgetWindow);
  123. InvalidateRect(widgetWindow, NULL, TRUE);
  124. }
  125. }
  126. }
  127. static void
  128. WidgetHost_UpdateFont(HWND hwnd, BOOL redraw)
  129. {
  130. WidgetHost *self;
  131. BOOL styleChanged = FALSE;
  132. long unitWidth, unitHeight;
  133. WIDGETHOST_RET_VOID(self, hwnd);
  134. if (FALSE == Graphics_GetWindowBaseUnits(hwnd, &unitWidth, &unitHeight))
  135. {
  136. unitWidth = 6;
  137. unitHeight = 13;
  138. }
  139. if (FALSE != WidgetStyle_UpdateDefaultFonts(&self->widgetStyle, self->font, unitWidth, unitHeight))
  140. styleChanged = TRUE;
  141. if (FALSE != styleChanged)
  142. {
  143. HWND widgetWindow = WIDGETHOST_WIDGET(hwnd);
  144. if (NULL != widgetWindow)
  145. {
  146. WIDGET_STYLE_COLOR_CHANGED(widgetWindow);
  147. InvalidateRect(widgetWindow, NULL, TRUE);
  148. }
  149. }
  150. }
  151. static LRESULT
  152. WidgetHost_OnCreate(HWND hwnd, CREATESTRUCT *createStruct)
  153. {
  154. WidgetHost *self;
  155. HWND widgetWindow;
  156. WidgetHostCreateParam *createParam;
  157. if (NULL == createStruct)
  158. return -1;
  159. createParam = (WidgetHostCreateParam*)createStruct->lpCreateParams;
  160. if (NULL == createParam)
  161. return -1;
  162. self = (WidgetHost*)malloc(sizeof(WidgetHost));
  163. if (NULL == self)
  164. return -1;
  165. SetLastError(ERROR_SUCCESS);
  166. if (!SetWindowLongPtr(hwnd, 0, (LONGX86)self) && ERROR_SUCCESS != GetLastError())
  167. return -1;
  168. memset(self, 0, sizeof(WidgetHost));
  169. WIDGETHOST_FREEZE(self);
  170. MLSkinWindow2(Plugin_GetLibraryWindow(), hwnd, SKINNEDWND_TYPE_WINDOW,
  171. SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS);
  172. WidgetHost_UpdateFont(hwnd, FALSE);
  173. WidgetHost_UpdateSkin(hwnd);
  174. widgetWindow = NULL;
  175. if (NULL != createParam->widgetCreate)
  176. widgetWindow = createParam->widgetCreate(hwnd, createParam->widgetCreateParam);
  177. if (NULL == widgetWindow)
  178. return -1;
  179. SetWindowLongPtrW(widgetWindow, GWLP_ID, WIDGETHOST_WIDGET_ID);
  180. WIDGET_SET_STYLE(widgetWindow, &self->widgetStyle);
  181. SetWindowPos(widgetWindow, NULL, 0, 0, 0, 0,
  182. SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW | SWP_FRAMECHANGED);
  183. ShowWindow(widgetWindow, SW_SHOWNA);
  184. SetWindowPos(widgetWindow, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
  185. WIDGETHOST_THAW(self);
  186. SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
  187. SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
  188. return 0;
  189. }
  190. static void
  191. WidgetHost_OnDestroy(HWND hwnd)
  192. {
  193. WidgetHost *self;
  194. self = WIDGETHOST(hwnd);
  195. SetWindowLongPtr(hwnd, 0, 0);
  196. if (NULL == self)
  197. return;
  198. WIDGETHOST_FREEZE(self);
  199. WidgetStyle_Free(&self->widgetStyle);
  200. free(self);
  201. }
  202. static void
  203. WidgetHost_OnPaint(HWND hwnd)
  204. {
  205. PAINTSTRUCT ps;
  206. if (NULL != BeginPaint(hwnd, &ps))
  207. {
  208. WidgetHost_Paint(hwnd, ps.hdc, &ps.rcPaint, ps.fErase);
  209. EndPaint(hwnd, &ps);
  210. }
  211. }
  212. static void
  213. WidgetHost_OnPrintClient(HWND hwnd, HDC hdc, UINT options)
  214. {
  215. RECT clientRect;
  216. if (GetClientRect(hwnd, &clientRect))
  217. {
  218. WidgetHost_Paint(hwnd, hdc, &clientRect, TRUE);
  219. }
  220. }
  221. static void
  222. WidgetHost_OnWindowPosChanged(HWND hwnd, WINDOWPOS *windowPos)
  223. {
  224. if ((SWP_NOSIZE | SWP_NOMOVE) != ((SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED) & windowPos->flags))
  225. {
  226. WidgetHost *self;
  227. WIDGETHOST_RET_VOID(self, hwnd);
  228. if (FALSE != WIDGETHOST_IS_FROZEN(self))
  229. return;
  230. WidgetHost_Layout(hwnd, 0 == (SWP_NOREDRAW & windowPos->flags));
  231. }
  232. }
  233. static void
  234. WidgetHost_OnDisplayChanged(HWND hwnd, INT bpp, INT dpi_x, INT dpi_y)
  235. {
  236. WidgetHost *self;
  237. WIDGETHOST_RET_VOID(self, hwnd);
  238. if (FALSE != WIDGETHOST_IS_FROZEN(self))
  239. return;
  240. WidgetHost_UpdateSkin(hwnd);
  241. InvalidateRect(hwnd, NULL, TRUE);
  242. }
  243. static void
  244. WidgetHost_OnSetFont(HWND hwnd, HFONT font, BOOL redraw)
  245. {
  246. WidgetHost *self;
  247. LOGFONTW prevFont, newFont;
  248. WIDGETHOST_RET_VOID(self, hwnd);
  249. if (NULL == self->font ||
  250. sizeof(LOGFONTW) != GetObjectW(self->font, sizeof(prevFont), &prevFont))
  251. {
  252. ZeroMemory(&prevFont, sizeof(prevFont));
  253. }
  254. self->font = font;
  255. if (NULL == self->font ||
  256. sizeof(newFont) != GetObjectW(self->font, sizeof(newFont), &newFont))
  257. {
  258. ZeroMemory(&newFont, sizeof(newFont));
  259. }
  260. if (0 != memcmp(&prevFont, &newFont, sizeof(prevFont)) &&
  261. FALSE == WIDGETHOST_IS_FROZEN(self))
  262. {
  263. WidgetHost_UpdateFont(hwnd, redraw);
  264. }
  265. }
  266. static HFONT
  267. WidgetHost_OnGetFont(HWND hwnd)
  268. {
  269. WidgetHost *self;
  270. WIDGETHOST_RET_VAL(self, hwnd, NULL);
  271. return self->font;
  272. }
  273. static void
  274. WidgetHost_OnSetUpdateRegion(HWND hwnd, HRGN updateRegion, POINTS regionOffset)
  275. {
  276. WidgetHost *self;
  277. WIDGETHOST_RET_VOID(self, hwnd);
  278. self->updateRegion = updateRegion;
  279. self->updateOffset.x = regionOffset.x;
  280. self->updateOffset.y = regionOffset.y;
  281. }
  282. static LRESULT CALLBACK
  283. WidgetHost_WindowProc(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam)
  284. {
  285. switch(uMsg)
  286. {
  287. case WM_CREATE: return WidgetHost_OnCreate(hwnd, (CREATESTRUCT*)lParam);
  288. case WM_DESTROY: WidgetHost_OnDestroy(hwnd); return 0;
  289. case WM_PAINT: WidgetHost_OnPaint(hwnd); return 0;
  290. case WM_PRINTCLIENT: WidgetHost_OnPrintClient(hwnd, (HDC)wParam, (UINT)lParam); return 0;
  291. case WM_PRINT: return 0;
  292. case WM_ERASEBKGND: return 0;
  293. case WM_WINDOWPOSCHANGED: WidgetHost_OnWindowPosChanged(hwnd, (WINDOWPOS*)lParam); return 0;
  294. case WM_SIZE: return 0;
  295. case WM_MOVE: return 0;
  296. case WM_DISPLAYCHANGE: WidgetHost_OnDisplayChanged(hwnd, (INT)wParam, LOWORD(lParam), HIWORD(lParam)); return 0;
  297. case WM_SETFONT: WidgetHost_OnSetFont(hwnd, (HFONT)wParam, LOWORD(lParam)); return 0;
  298. case WM_GETFONT: return (LRESULT)WidgetHost_OnGetFont(hwnd);
  299. // gen_ml flickerless drawing
  300. case WM_USER + 0x200: return 1;
  301. case WM_USER + 0x201: WidgetHost_OnSetUpdateRegion(hwnd, (HRGN)lParam, MAKEPOINTS(wParam)); return 0;
  302. }
  303. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  304. }