Picker.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. // PickerClass.cpp : implementation file
  19. //
  20. #include "stdafx.h"
  21. #include "leveledit.h"
  22. #include "picker.h"
  23. #include "utils.h"
  24. #include "filemgr.h"
  25. #ifdef _DEBUG
  26. #define new DEBUG_NEW
  27. #undef THIS_FILE
  28. static char THIS_FILE[] = __FILE__;
  29. #endif
  30. ///////////////////////////////////////////////////////////
  31. // Local constants
  32. ///////////////////////////////////////////////////////////
  33. const int BUTTON_WIDTH = 22;
  34. const int BUTTON_ID = 101;
  35. const int EDIT_ID = 102;
  36. ///////////////////////////////////////////////////////////
  37. //
  38. // PickerClass
  39. //
  40. ///////////////////////////////////////////////////////////
  41. PickerClass::PickerClass (void)
  42. : m_BrowseButton (NULL),
  43. m_Icon (NULL),
  44. CStatic ()
  45. {
  46. //
  47. // By default load the folder icon
  48. //
  49. m_Icon = (HICON)::LoadImage (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDI_FOLDER_TINY), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
  50. return ;
  51. }
  52. ///////////////////////////////////////////////////////////
  53. //
  54. // ~PickerClass
  55. //
  56. ///////////////////////////////////////////////////////////
  57. PickerClass::~PickerClass (void)
  58. {
  59. return ;
  60. }
  61. BEGIN_MESSAGE_MAP(PickerClass, CStatic)
  62. //{{AFX_MSG_MAP(PickerClass)
  63. ON_WM_SIZE()
  64. ON_WM_DRAWITEM()
  65. ON_WM_ERASEBKGND()
  66. ON_WM_PAINT()
  67. //}}AFX_MSG_MAP
  68. END_MESSAGE_MAP()
  69. ///////////////////////////////////////////////////////////
  70. //
  71. // Create_Picker
  72. //
  73. ///////////////////////////////////////////////////////////
  74. bool
  75. PickerClass::Create_Picker
  76. (
  77. DWORD style,
  78. const RECT & rect,
  79. CWnd * parent,
  80. UINT id
  81. )
  82. {
  83. //
  84. // Create the outer window
  85. //
  86. BOOL success = CreateEx ( WS_EX_CLIENTEDGE,
  87. "STATIC",
  88. "",
  89. (style | SS_WHITERECT | WS_CLIPCHILDREN) & (~WS_BORDER),
  90. rect,
  91. parent,
  92. id);
  93. if (success) {
  94. Initialize_Control ();
  95. }
  96. // Return the true/false result code
  97. return bool(success == TRUE);
  98. }
  99. ///////////////////////////////////////////////////////////
  100. //
  101. // WindowProc
  102. //
  103. ///////////////////////////////////////////////////////////
  104. LRESULT
  105. PickerClass::WindowProc
  106. (
  107. UINT message,
  108. WPARAM wParam,
  109. LPARAM lParam
  110. )
  111. {
  112. //
  113. // Should we just pass this onto the edit control?
  114. //
  115. if ((message == WM_GETTEXT) ||
  116. (message == WM_GETTEXTLENGTH) ||
  117. (message == WM_SETTEXT))
  118. {
  119. return SendDlgItemMessage (EDIT_ID, message, wParam, lParam);
  120. } else if ((message == WM_COMMAND) && (LOWORD (wParam) == EDIT_ID)) {
  121. //
  122. // Translate the message so the dialog thinks it came from an
  123. // edit control
  124. //
  125. LONG id = ::GetWindowLong (m_hWnd, GWL_ID);
  126. return ::SendMessage (::GetParent (m_hWnd),
  127. message,
  128. MAKEWPARAM (id & 0xFFFF, HIWORD (wParam)),
  129. (LPARAM)m_hWnd);
  130. } else if (message == WM_SETFOCUS) {
  131. ::SetFocus (::GetDlgItem (m_hWnd, EDIT_ID));
  132. }
  133. return CStatic::WindowProc (message, wParam, lParam);
  134. }
  135. ///////////////////////////////////////////////////////////
  136. //
  137. // Initialize_Control
  138. //
  139. ///////////////////////////////////////////////////////////
  140. void
  141. PickerClass::Initialize_Control (void)
  142. {
  143. //
  144. // Set the font for this control
  145. //
  146. HFONT hfont = (HFONT)GetParent()->SendMessage (WM_GETFONT);
  147. SendMessage (WM_SETFONT, (WPARAM)hfont);
  148. //
  149. // Determine how tall to make the edit control
  150. //
  151. HDC hdc = ::GetDC (m_hWnd);
  152. HFONT holdfont = (HFONT)::SelectObject (hdc, hfont);
  153. CSize size;
  154. ::GetTextExtentPoint32 (hdc, "XgW", 3, &size);
  155. ::SelectObject (hdc, holdfont);
  156. ::ReleaseDC (m_hWnd, hdc);
  157. //
  158. // Create the edit control
  159. //
  160. CRect rect;
  161. GetClientRect (&rect);
  162. m_EditCtrl = ::CreateWindowEx ( 0,
  163. "EDIT",
  164. "",
  165. WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL,
  166. 2,
  167. (rect.Height () >> 1) - ((size.cy) >> 1),
  168. rect.Width () - BUTTON_WIDTH - 3,
  169. size.cy,
  170. m_hWnd,
  171. (HMENU)EDIT_ID,
  172. ::AfxGetInstanceHandle (),
  173. NULL);
  174. CRect rect2;
  175. GetWindowRect (&rect2);
  176. ::SendMessage (m_EditCtrl, WM_SETFONT, (WPARAM)hfont, 0L);
  177. //
  178. // Create the picker button
  179. //
  180. m_BrowseButton = ::CreateWindow ("BUTTON",
  181. "",
  182. WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_OWNERDRAW,
  183. rect.Width () - BUTTON_WIDTH,
  184. 0,
  185. BUTTON_WIDTH,
  186. rect.Height (),
  187. m_hWnd,
  188. (HMENU)BUTTON_ID,
  189. ::AfxGetInstanceHandle (),
  190. NULL);
  191. ASSERT (m_BrowseButton != NULL);
  192. return ;
  193. }
  194. ///////////////////////////////////////////////////////////
  195. //
  196. // Initialize_Control
  197. //
  198. ///////////////////////////////////////////////////////////
  199. void
  200. PickerClass::OnSize
  201. (
  202. UINT nType,
  203. int cx,
  204. int cy
  205. )
  206. {
  207. //
  208. // Set the font for this control
  209. //
  210. HFONT hfont = (HFONT)GetParent()->SendMessage (WM_GETFONT);
  211. SendMessage (WM_SETFONT, (WPARAM)hfont);
  212. //
  213. // Determine how tall to make the edit control
  214. //
  215. HDC hdc = ::GetDC (m_hWnd);
  216. HFONT holdfont = (HFONT)::SelectObject (hdc, hfont);
  217. CSize size;
  218. ::GetTextExtentPoint32 (hdc, "XgW", 3, &size);
  219. ::SelectObject (hdc, holdfont);
  220. ::ReleaseDC (m_hWnd, hdc);
  221. CRect client_rect;
  222. GetClientRect (&client_rect);
  223. //
  224. // Resize the edit control
  225. //
  226. ::SetWindowPos ( m_EditCtrl,
  227. NULL,
  228. 2,
  229. (client_rect.Height () >> 1) - ((size.cy) >> 1),
  230. client_rect.Width () - BUTTON_WIDTH - 3,
  231. size.cy,
  232. SWP_NOZORDER);
  233. //
  234. // Reposition the file button
  235. //
  236. ::SetWindowPos ( m_BrowseButton,
  237. NULL,
  238. client_rect.Width () - BUTTON_WIDTH,
  239. 0,
  240. BUTTON_WIDTH,
  241. client_rect.Height (),
  242. SWP_NOZORDER);
  243. CStatic::OnSize (nType, cx, cy);
  244. return ;
  245. }
  246. ///////////////////////////////////////////////////////////
  247. //
  248. // OnCommand
  249. //
  250. ///////////////////////////////////////////////////////////
  251. BOOL
  252. PickerClass::OnCommand
  253. (
  254. WPARAM wParam,
  255. LPARAM lParam
  256. )
  257. {
  258. //
  259. // Did the user click the 'picker' button?
  260. //
  261. if ((LOWORD (wParam) == BUTTON_ID) &&
  262. (HIWORD (wParam) == BN_CLICKED))
  263. {
  264. On_Pick ();
  265. }
  266. // Allow the base class to process this message
  267. return CStatic::OnCommand (wParam, lParam);
  268. }
  269. ///////////////////////////////////////////////////////////
  270. //
  271. // OnDrawItem
  272. //
  273. ///////////////////////////////////////////////////////////
  274. void
  275. PickerClass::OnDrawItem
  276. (
  277. int nIDCtl,
  278. LPDRAWITEMSTRUCT pDrawItemStruct
  279. )
  280. {
  281. CRect rect;
  282. ::GetClientRect (m_BrowseButton, &rect);
  283. //
  284. // Draw the button frame
  285. //
  286. UINT type = (pDrawItemStruct->itemState & ODS_SELECTED) ? (DFCS_SCROLLDOWN | DFCS_PUSHED) : DFCS_SCROLLDOWN;
  287. ::DrawFrameControl (pDrawItemStruct->hDC, &rect, DFC_SCROLL, type);
  288. //
  289. // Calculate the icon's position
  290. //
  291. int xpos = (rect.Width () / 2) - 8;
  292. int ypos = (rect.Height () / 2) - 8;
  293. if (pDrawItemStruct->itemState & ODS_SELECTED) {
  294. xpos ++;
  295. ypos ++;
  296. }
  297. //
  298. // Paint the icon
  299. //
  300. ::DrawIconEx (pDrawItemStruct->hDC,
  301. xpos,
  302. ypos,
  303. m_Icon,
  304. 16,
  305. 16,
  306. 0,
  307. NULL,
  308. DI_NORMAL);
  309. CStatic::OnDrawItem (nIDCtl, pDrawItemStruct);
  310. return ;
  311. }
  312. ///////////////////////////////////////////////////////////
  313. //
  314. // Set_Read_Only
  315. //
  316. ///////////////////////////////////////////////////////////
  317. void
  318. PickerClass::Set_Read_Only (bool readonly)
  319. {
  320. ::SendMessage (m_EditCtrl, EM_SETREADONLY, (WPARAM)readonly, 0L);
  321. return ;
  322. }
  323. ///////////////////////////////////////////////////////////
  324. //
  325. // OnEraseBkgnd
  326. //
  327. ///////////////////////////////////////////////////////////
  328. BOOL
  329. PickerClass::OnEraseBkgnd (CDC *pDC)
  330. {
  331. CRect rect;
  332. ::GetClientRect (m_hWnd, &rect);
  333. //
  334. // Use the 'grayed' brush if this control is read-only
  335. //
  336. HBRUSH brush = HBRUSH(COLOR_WINDOW+1);
  337. if (::GetWindowLong (m_EditCtrl, GWL_STYLE) & ES_READONLY) {
  338. brush = HBRUSH(COLOR_3DFACE+1);
  339. }
  340. //
  341. // Erase the background
  342. //
  343. ::FillRect (*pDC, &rect, brush);
  344. return TRUE;
  345. }
  346. ///////////////////////////////////////////////////////////
  347. //
  348. // OnPaint
  349. //
  350. ///////////////////////////////////////////////////////////
  351. void
  352. PickerClass::OnPaint (void)
  353. {
  354. //
  355. // Force the child windows to be repainted
  356. //
  357. ::InvalidateRect (m_EditCtrl, NULL, TRUE);
  358. ::InvalidateRect (m_BrowseButton, NULL, TRUE);
  359. CPaintDC dc (this);
  360. return ;
  361. }