You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Dialog.cxx 8.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved.
  2. *
  3. * This is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This software is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  16. * USA.
  17. */
  18. // -=- Dialog.cxx
  19. // Base-class for any Dialog classes we might require
  20. #include <rfb_win32/Dialog.h>
  21. #include <rfb_win32/TCharArray.h>
  22. #include <rfb/LogWriter.h>
  23. #include <rdr/Exception.h>
  24. #include <rfb_win32/Win32Util.h>
  25. #ifdef _DIALOG_CAPTURE
  26. #include <rfb_win32/DeviceFrameBuffer.h>
  27. #include <extra/LoadBMP.cxx>
  28. #endif
  29. using namespace rfb;
  30. using namespace rfb::win32;
  31. static LogWriter dlog("Dialog");
  32. static LogWriter plog("PropSheet");
  33. Dialog::Dialog(HINSTANCE inst_)
  34. : inst(inst_), alreadyShowing(false), handle(0)
  35. {
  36. }
  37. Dialog::~Dialog()
  38. {
  39. }
  40. bool Dialog::showDialog(const TCHAR* resource, HWND owner)
  41. {
  42. if (alreadyShowing) return false;
  43. handle = 0;
  44. alreadyShowing = true;
  45. INT_PTR result = DialogBoxParam(inst, resource, owner,
  46. staticDialogProc, (LPARAM)this);
  47. if (result<0)
  48. throw rdr::SystemException("DialogBoxParam failed", GetLastError());
  49. alreadyShowing = false;
  50. return (result == 1);
  51. }
  52. bool Dialog::isItemChecked(int id) {
  53. return SendMessage(GetDlgItem(handle, id), BM_GETCHECK, 0, 0) == BST_CHECKED;
  54. }
  55. int Dialog::getItemInt(int id) {
  56. BOOL trans;
  57. int result = GetDlgItemInt(handle, id, &trans, TRUE);
  58. if (!trans)
  59. throw rdr::Exception("unable to read dialog Int");
  60. return result;
  61. }
  62. TCHAR* Dialog::getItemString(int id) {
  63. TCharArray tmp(256);
  64. if (!GetDlgItemText(handle, id, tmp.buf, 256))
  65. tmp.buf[0] = 0;
  66. return tmp.takeBuf();
  67. }
  68. void Dialog::setItemChecked(int id, bool state) {
  69. dlog.debug("bool[%d]=%d", id, (int)state);
  70. SendMessage(GetDlgItem(handle, id), BM_SETCHECK, state ? BST_CHECKED : BST_UNCHECKED, 0);
  71. }
  72. void Dialog::setItemInt(int id, int value) {
  73. dlog.debug("int[%d]=%d", id, value);
  74. SetDlgItemInt(handle, id, value, TRUE);
  75. }
  76. void Dialog::setItemString(int id, const TCHAR* s) {
  77. dlog.debug("string[%d]=%s", id, (const char*)CStr(s));
  78. SetDlgItemText(handle, id, s);
  79. }
  80. void Dialog::enableItem(int id, bool state) {
  81. dlog.debug("enable[%d]=%d", id, (int)state);
  82. EnableWindow(GetDlgItem(handle, id), state);
  83. }
  84. BOOL CALLBACK Dialog::staticDialogProc(HWND hwnd, UINT msg,
  85. WPARAM wParam, LPARAM lParam)
  86. {
  87. if (msg == WM_INITDIALOG)
  88. SetWindowLong(hwnd, GWL_USERDATA, (LONG)lParam);
  89. LONG self = GetWindowLong(hwnd, GWL_USERDATA);
  90. if (!self) return FALSE;
  91. return ((Dialog*)self)->dialogProc(hwnd, msg, wParam, lParam);
  92. }
  93. BOOL Dialog::dialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  94. {
  95. switch (msg) {
  96. case WM_INITDIALOG:
  97. handle = hwnd;
  98. initDialog();
  99. return TRUE;
  100. case WM_COMMAND:
  101. switch (LOWORD(wParam)) {
  102. case IDOK:
  103. if (onOk()) {
  104. EndDialog(hwnd, 1);
  105. return TRUE;
  106. }
  107. return FALSE;
  108. case IDCANCEL:
  109. EndDialog(hwnd, 0);
  110. return TRUE;
  111. default:
  112. return onCommand(LOWORD(wParam), HIWORD(wParam));
  113. };
  114. case WM_HELP:
  115. return onHelp(((HELPINFO*)lParam)->iCtrlId);
  116. }
  117. return FALSE;
  118. }
  119. PropSheetPage::PropSheetPage(HINSTANCE inst, const TCHAR* id) : Dialog(inst), propSheet(0) {
  120. page.dwSize = sizeof(page);
  121. page.dwFlags = 0; // PSP_USECALLBACK;
  122. page.hInstance = inst;
  123. page.pszTemplate = id;
  124. page.pfnDlgProc = staticPageProc;
  125. page.lParam = (LPARAM)this;
  126. page.pfnCallback = 0; // staticPageProc;
  127. }
  128. PropSheetPage::~PropSheetPage() {
  129. }
  130. BOOL CALLBACK PropSheetPage::staticPageProc(HWND hwnd, UINT msg,
  131. WPARAM wParam, LPARAM lParam)
  132. {
  133. if (msg == WM_INITDIALOG)
  134. SetWindowLong(hwnd, GWL_USERDATA, ((PROPSHEETPAGE*)lParam)->lParam);
  135. LONG self = GetWindowLong(hwnd, GWL_USERDATA);
  136. if (!self) return FALSE;
  137. return ((PropSheetPage*)self)->dialogProc(hwnd, msg, wParam, lParam);
  138. }
  139. BOOL PropSheetPage::dialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  140. {
  141. switch (msg) {
  142. case WM_INITDIALOG:
  143. handle = hwnd;
  144. initDialog();
  145. return TRUE;
  146. case WM_NOTIFY:
  147. switch (((NMHDR*)lParam)->code) {
  148. case PSN_APPLY:
  149. onOk();
  150. return FALSE;
  151. };
  152. return FALSE;
  153. case WM_COMMAND:
  154. return onCommand(LOWORD(wParam), HIWORD(wParam));
  155. case WM_HELP:
  156. return onHelp(((HELPINFO*)lParam)->iCtrlId);
  157. }
  158. return FALSE;
  159. }
  160. PropSheet::PropSheet(HINSTANCE inst_, const TCHAR* title_, std::list<PropSheetPage*> pages_, HICON icon_)
  161. : title(tstrDup(title_)), inst(inst_), pages(pages_), alreadyShowing(0), handle(0), icon(icon_) {
  162. }
  163. PropSheet::~PropSheet() {
  164. }
  165. bool PropSheet::showPropSheet(HWND owner, bool showApply, bool showCtxtHelp, bool capture) {
  166. if (alreadyShowing) return false;
  167. alreadyShowing = true;
  168. int count = pages.size();
  169. HPROPSHEETPAGE* hpages = new HPROPSHEETPAGE[count];
  170. try {
  171. // Create the PropertSheet page GDI objects.
  172. std::list<PropSheetPage*>::iterator pspi;
  173. int i = 0;
  174. for (pspi=pages.begin(); pspi!=pages.end(); pspi++) {
  175. hpages[i] = CreatePropertySheetPage(&((*pspi)->page));
  176. (*pspi)->setPropSheet(this);
  177. i++;
  178. }
  179. // Initialise and create the PropertySheet itself
  180. PROPSHEETHEADER header;
  181. header.dwSize = PROPSHEETHEADER_V1_SIZE;
  182. header.dwFlags = PSH_MODELESS | (showApply ? 0 : PSH_NOAPPLYNOW) /*| (showCtxtHelp ? 0 : PSH_NOCONTEXTHELP)*/;
  183. header.hwndParent = owner;
  184. header.hInstance = inst;
  185. header.pszCaption = title.buf;
  186. header.nPages = count;
  187. header.nStartPage = 0;
  188. header.phpage = hpages;
  189. if (icon) {
  190. header.hIcon = icon;
  191. header.dwFlags |= PSH_USEHICON;
  192. }
  193. handle = (HWND)PropertySheet(&header);
  194. if ((handle == 0) || (handle == (HWND)-1))
  195. throw rdr::SystemException("PropertySheet failed", GetLastError());
  196. centerWindow(handle, owner);
  197. plog.info("created %lx", handle);
  198. #if (WINVER >= 0x0500)
  199. #ifdef _DIALOG_CAPTURE
  200. // *** NOT TESTED
  201. if (capture) {
  202. plog.info("capturing \"%s\"", (const char*)CStr(title.buf));
  203. char* tmpdir = getenv("TEMP");
  204. HDC dc = GetWindowDC(handle);
  205. DeviceFrameBuffer fb(dc);
  206. int i=0;
  207. while (true) {
  208. int id = PropSheet_IndexToId(handle, i);
  209. if (!id) break;
  210. PropSheet_SetCurSelByID(handle, id);
  211. MSG msg;
  212. while (PeekMessage(&msg, handle, 0, 0, PM_REMOVE)) {
  213. if (!PropSheet_IsDialogMessage(handle, &msg))
  214. DispatchMessage(&msg);
  215. }
  216. fb.grabRect(fb.getRect());
  217. char filename[256];
  218. sprintf(filename, "%s\\capture%d.bmp", tmpdir, i);
  219. saveBMP(filename, &fb);
  220. i++;
  221. }
  222. ReleaseDC(handle, dc);
  223. } else {
  224. #endif
  225. #endif
  226. try {
  227. if (owner)
  228. EnableWindow(owner, FALSE);
  229. // Run the PropertySheet
  230. MSG msg;
  231. while (GetMessage(&msg, 0, 0, 0)) {
  232. if (!PropSheet_IsDialogMessage(handle, &msg))
  233. DispatchMessage(&msg);
  234. if (!PropSheet_GetCurrentPageHwnd(handle))
  235. break;
  236. }
  237. if (owner)
  238. EnableWindow(owner, TRUE);
  239. } catch (...) {
  240. if (owner)
  241. EnableWindow(owner, TRUE);
  242. throw;
  243. }
  244. #if (WINVER >= 0x0500)
  245. #ifdef _DIALOG_CAPTURE
  246. }
  247. #endif
  248. #endif
  249. plog.info("finished %lx", handle);
  250. DestroyWindow(handle);
  251. handle = 0;
  252. alreadyShowing = false;
  253. // Clear up the pages' GDI objects
  254. for (pspi=pages.begin(); pspi!=pages.end(); pspi++)
  255. (*pspi)->setPropSheet(0);
  256. delete [] hpages; hpages = 0;
  257. return true;
  258. } catch (rdr::Exception) {
  259. alreadyShowing = false;
  260. std::list<PropSheetPage*>::iterator pspi;
  261. for (pspi=pages.begin(); pspi!=pages.end(); pspi++)
  262. (*pspi)->setPropSheet(0);
  263. delete [] hpages; hpages = 0;
  264. throw;
  265. }
  266. }
  267. void PropSheet::reInitPages() {
  268. plog.debug("reInitPages %lx", handle);
  269. std::list<PropSheetPage*>::iterator pspi;
  270. for (pspi=pages.begin(); pspi!=pages.end(); pspi++) {
  271. if ((*pspi)->handle)
  272. (*pspi)->initDialog();
  273. }
  274. }
  275. bool PropSheet::commitPages() {
  276. plog.debug("commitPages %lx", handle);
  277. bool result = true;
  278. std::list<PropSheetPage*>::iterator pspi;
  279. for (pspi=pages.begin(); pspi!=pages.end(); pspi++) {
  280. if ((*pspi)->handle)
  281. result = result && (*pspi)->onOk();
  282. }
  283. return result;
  284. }
  285. void PropSheetPage::setChanged(bool changed) {
  286. if (propSheet) {
  287. plog.debug("setChanged[%lx(%lx)]=%d", handle, propSheet->handle, (int)changed);
  288. if (changed)
  289. PropSheet_Changed(propSheet->handle, handle);
  290. else
  291. PropSheet_UnChanged(propSheet->handle, handle);
  292. }
  293. }