VCLCommon.cpp 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include "WinInterface.h"
  5. #include "VCLCommon.h"
  6. #include <Common.h>
  7. #include <TextsWin.h>
  8. #include <RemoteFiles.h>
  9. #include <GUITools.h>
  10. #include <Tools.h>
  11. #include <FileCtrl.hpp>
  12. #include <ThemeMgr.hpp>
  13. #include <PathLabel.hpp>
  14. //---------------------------------------------------------------------------
  15. #pragma package(smart_init)
  16. //---------------------------------------------------------------------------
  17. static TThemeManager * ThemeManager = NULL;
  18. //---------------------------------------------------------------------------
  19. void __fastcall AdjustListColumnsWidth(TListView* ListView, int RowCount, int RightPad)
  20. {
  21. int OriginalWidth, NewWidth, i, CWidth, LastResizible;
  22. OriginalWidth = 0;
  23. LastResizible = -1;
  24. for (i = 0; i < ListView->Columns->Count; i++)
  25. {
  26. OriginalWidth += ListView->Columns->Items[i]->Width;
  27. if (ListView->Columns->Items[i]->Tag == 0)
  28. {
  29. LastResizible = i;
  30. }
  31. }
  32. assert(LastResizible >= 0);
  33. // when listview is virtual, ListView->Items->Count seems to return invalid
  34. // value, thus provide a method to pass actual count explicitly
  35. if (RowCount < 0)
  36. {
  37. RowCount = ListView->Items->Count;
  38. }
  39. NewWidth = 0;
  40. CWidth = ListView->ClientWidth - RightPad;
  41. if ((ListView->VisibleRowCount < RowCount) &&
  42. (ListView->Width - ListView->ClientWidth < GetSystemMetrics(SM_CXVSCROLL)))
  43. {
  44. CWidth -= GetSystemMetrics(SM_CXVSCROLL);
  45. }
  46. for (i = 0; i < ListView->Columns->Count; i++)
  47. {
  48. if (i != LastResizible)
  49. {
  50. if (ListView->Columns->Items[i]->Tag == 0)
  51. {
  52. ListView->Columns->Items[i]->Width =
  53. (CWidth * ListView->Columns->Items[i]->Width) / OriginalWidth;
  54. }
  55. NewWidth += ListView->Columns->Items[i]->Width;
  56. }
  57. }
  58. ListView->Columns->Items[LastResizible]->Width = CWidth-NewWidth;
  59. }
  60. //---------------------------------------------------------------------------
  61. static void __fastcall SetParentColor(TControl * Control)
  62. {
  63. TColor Color;
  64. assert(ThemeManager != NULL);
  65. if (ThemeManager->ThemesEnabled)
  66. {
  67. bool OnTabSheet = false;
  68. TWinControl * Parent = Control->Parent;
  69. while ((Parent != NULL) && !OnTabSheet)
  70. {
  71. TTabSheet * TabSheet = dynamic_cast<TTabSheet *>(Parent);
  72. OnTabSheet = (TabSheet != NULL) && TabSheet->TabVisible;
  73. Parent = Parent->Parent;
  74. }
  75. if (OnTabSheet)
  76. {
  77. Color = ThemeManager->GetColor(teTab, ::TABP_BODY, 0, ::TMT_FILLCOLORHINT);
  78. }
  79. else
  80. {
  81. Color = ThemeManager->GetColor(teWindow, ::WP_DIALOG, 0, ::TMT_FILLCOLOR);
  82. }
  83. }
  84. else
  85. {
  86. Color = clBtnFace;
  87. }
  88. ((TEdit*)Control)->Color = Color;
  89. }
  90. //---------------------------------------------------------------------------
  91. void __fastcall EnableControl(TControl * Control, bool Enable)
  92. {
  93. if (Control->Enabled != Enable)
  94. {
  95. if (Control->InheritsFrom(__classid(TWinControl)) &&
  96. (((TWinControl*)Control)->ControlCount > 0))
  97. {
  98. for (Integer Index = 0; Index < ((TWinControl*)Control)->ControlCount; Index++)
  99. EnableControl(((TWinControl*)Control)->Controls[Index], Enable);
  100. }
  101. Control->Enabled = Enable;
  102. }
  103. if (Control->InheritsFrom(__classid(TCustomEdit)) ||
  104. Control->InheritsFrom(__classid(TCustomComboBox)) ||
  105. Control->InheritsFrom(__classid(TCustomListView)))
  106. {
  107. if (Enable)
  108. {
  109. ((TEdit*)Control)->Color = clWindow;
  110. }
  111. else
  112. {
  113. ((TEdit*)Control)->Color = clBtnFace;
  114. }
  115. }
  116. };
  117. //---------------------------------------------------------------------------
  118. void __fastcall ReadOnlyControl(TControl * Control, bool ReadOnly)
  119. {
  120. if (Control->InheritsFrom(__classid(TCustomEdit)))
  121. {
  122. ((TEdit*)Control)->ReadOnly = ReadOnly;
  123. if (ReadOnly)
  124. {
  125. SetParentColor(Control);
  126. }
  127. else
  128. {
  129. ((TEdit*)Control)->Color = clWindow;
  130. }
  131. }
  132. else
  133. {
  134. assert(false);
  135. }
  136. }
  137. //---------------------------------------------------------------------------
  138. struct TSavedSystemSettings
  139. {
  140. TCustomForm * Form;
  141. AnsiString FontName;
  142. bool Flipped;
  143. TWndMethod OldWndProc;
  144. };
  145. //---------------------------------------------------------------------------
  146. static void __fastcall ThemeManagerAllowSubclassing(void * /*Data*/,
  147. TThemeManager * /*Sender*/, TControl * Control, bool & Allow)
  148. {
  149. TPathLabel * PathLabel = dynamic_cast<TPathLabel *>(Control);
  150. // intent is to only exclude path labels on the main window
  151. if ((PathLabel != NULL) && (PathLabel->FocusControl != NULL))
  152. {
  153. Allow = false;
  154. }
  155. // tree view on location profiles dialog occasionally does not show,
  156. // it is unique in that is is placed on group box (however I'm not sure if
  157. // it is the property that makes it not work)
  158. if ((dynamic_cast<TTreeView *>(Control) != NULL) &&
  159. (dynamic_cast<TCustomGroupBox *>(Control->Parent) != NULL))
  160. {
  161. Allow = false;
  162. }
  163. }
  164. //---------------------------------------------------------------------------
  165. class TPublicControl : public TWinControl
  166. {
  167. friend TWndMethod __fastcall ControlWndProc(TWinControl * Control);
  168. };
  169. //---------------------------------------------------------------------------
  170. TWndMethod __fastcall ControlWndProc(TWinControl * Control)
  171. {
  172. TPublicControl * PublicControl = static_cast<TPublicControl *>(Control);
  173. return &PublicControl->WndProc;
  174. }
  175. //---------------------------------------------------------------------------
  176. inline void __fastcall DoFormWindowProc(TCustomForm * Form, TWndMethod WndProc,
  177. TMessage & Message)
  178. {
  179. if ((Message.Msg == WM_SYSCOMMAND) &&
  180. (Message.WParam == SC_CONTEXTHELP))
  181. {
  182. InvokeHelp(Form->ActiveControl);
  183. Message.Result = 1;
  184. }
  185. else
  186. {
  187. WndProc(Message);
  188. }
  189. }
  190. //---------------------------------------------------------------------------
  191. static void __fastcall FormWindowProc(void * Data, TMessage & Message)
  192. {
  193. TCustomForm * Form = static_cast<TCustomForm *>(Data);
  194. DoFormWindowProc(Form, ControlWndProc(Form), Message);
  195. }
  196. //---------------------------------------------------------------------------
  197. static void __fastcall FormWindowProcEx(void * Data, TMessage & Message)
  198. {
  199. TSavedSystemSettings * SSettings = static_cast<TSavedSystemSettings *>(Data);
  200. DoFormWindowProc(SSettings->Form, SSettings->OldWndProc, Message);
  201. }
  202. //---------------------------------------------------------------------------
  203. void __fastcall InitSystemSettings(TComponent * Control)
  204. {
  205. if (ThemeManager == NULL)
  206. {
  207. assert(Control->FindComponent("ThemeManager") == NULL);
  208. ThemeManager = new TThemeManager(Control);
  209. ThemeManager->Name = "ThemeManager";
  210. // ListView subclassing breaks TDirView
  211. ThemeManager->Options = (ThemeManager->Options >> toSubclassListView);
  212. // Speed Button subclassing on rights frame does not work somehow
  213. // and they are not used elsewhere
  214. ThemeManager->Options = (ThemeManager->Options >> toSubclassSpeedButtons);
  215. TAllowSubclassingEvent OnAllowSubclassing;
  216. ((TMethod*)&OnAllowSubclassing)->Code = ThemeManagerAllowSubclassing;
  217. ThemeManager->OnAllowSubclassing = OnAllowSubclassing;
  218. }
  219. }
  220. //---------------------------------------------------------------------------
  221. // Settings that must be set as soon as possible.
  222. void __fastcall UseSystemSettingsPre(TCustomForm * Control, void ** Settings)
  223. {
  224. TWndMethod WindowProc;
  225. if (Settings)
  226. {
  227. TSavedSystemSettings * SSettings;
  228. SSettings = new TSavedSystemSettings();
  229. *Settings = static_cast<void*>(SSettings);
  230. SSettings->Form = Control;
  231. SSettings->FontName = Control->Font->Name;
  232. SSettings->OldWndProc = Control->WindowProc;
  233. ((TMethod*)&WindowProc)->Data = SSettings;
  234. ((TMethod*)&WindowProc)->Code = FormWindowProcEx;
  235. }
  236. else
  237. {
  238. ((TMethod*)&WindowProc)->Data = Control;
  239. ((TMethod*)&WindowProc)->Code = FormWindowProc;
  240. }
  241. Control->WindowProc = WindowProc;
  242. assert(Control && Control->Font);
  243. Control->Font->Name = "MS Shell Dlg";
  244. if (Control->HelpKeyword.IsEmpty())
  245. {
  246. // temporary help keyword to enable F1 key in all forms
  247. Control->HelpKeyword = "start";
  248. }
  249. // especially on login dialog, we need to reapply themes with language change
  250. if (ThemeManager != NULL)
  251. {
  252. ThemeManager->CollectControls(Control);
  253. }
  254. };
  255. //---------------------------------------------------------------------------
  256. // Settings that must be set only after whole form is constructed
  257. void __fastcall UseSystemSettingsPost(TCustomForm * Control, void * Settings)
  258. {
  259. bool Flip;
  260. AnsiString FlipStr = LoadStr(FLIP_CHILDREN);
  261. Flip = !FlipStr.IsEmpty() && static_cast<bool>(StrToInt(FlipStr));
  262. if (Settings != NULL)
  263. {
  264. static_cast<TSavedSystemSettings*>(Settings)->Flipped = Flip;
  265. }
  266. if (Flip)
  267. {
  268. Control->FlipChildren(true);
  269. }
  270. ResetSystemSettings(Control);
  271. };
  272. //---------------------------------------------------------------------------
  273. void __fastcall UseSystemSettings(TCustomForm * Control, void ** Settings)
  274. {
  275. UseSystemSettingsPre(Control, Settings);
  276. UseSystemSettingsPost(Control, (Settings != NULL) ? *Settings : NULL);
  277. };
  278. //---------------------------------------------------------------------------
  279. void __fastcall ResetSystemSettings(TCustomForm * /*Control*/)
  280. {
  281. // noop
  282. }
  283. //---------------------------------------------------------------------------
  284. void __fastcall DeleteSystemSettings(TCustomForm * Control, void * Settings)
  285. {
  286. assert(Settings);
  287. TSavedSystemSettings * SSettings = static_cast<TSavedSystemSettings *>(Settings);
  288. Control->WindowProc = SSettings->OldWndProc;
  289. delete SSettings;
  290. }
  291. //---------------------------------------------------------------------------
  292. void __fastcall RevokeSystemSettings(TCustomForm * Control, void * Settings)
  293. {
  294. assert(Settings);
  295. TSavedSystemSettings* SSettings = static_cast<TSavedSystemSettings*>(Settings);
  296. if (SSettings->Flipped)
  297. {
  298. Control->FlipChildren(true);
  299. }
  300. DeleteSystemSettings(Control, Settings);
  301. };
  302. //---------------------------------------------------------------------------
  303. class TPublicForm : public TForm
  304. {
  305. friend void __fastcall ShowAsModal(TForm * Form, void *& Storage);
  306. friend void __fastcall HideAsModal(TForm * Form, void *& Storage);
  307. };
  308. //---------------------------------------------------------------------------
  309. struct TShowAsModalStorage
  310. {
  311. void * FocusWindowList;
  312. void * FocusActiveWindow;
  313. TFocusState FocusState;
  314. };
  315. //---------------------------------------------------------------------------
  316. static TCustomForm ** __fastcall FocusedForm()
  317. {
  318. return reinterpret_cast<TCustomForm **>(reinterpret_cast<char *>(Screen) + 0x78);
  319. }
  320. //---------------------------------------------------------------------------
  321. static TList * __fastcall SaveFocusedList()
  322. {
  323. return *reinterpret_cast<TList **>(reinterpret_cast<char *>(Screen) + 0x7C);
  324. }
  325. //---------------------------------------------------------------------------
  326. void __fastcall ShowAsModal(TForm * Form, void *& Storage)
  327. {
  328. SetCorrectFormParent(Form);
  329. CancelDrag();
  330. if (GetCapture() != 0) SendMessage(GetCapture(), WM_CANCELMODE, 0, 0);
  331. ReleaseCapture();
  332. (static_cast<TPublicForm*>(Form))->FFormState << fsModal;
  333. TShowAsModalStorage * AStorage = new TShowAsModalStorage;
  334. AStorage->FocusActiveWindow = GetActiveWindow();
  335. AStorage->FocusState = SaveFocusState();
  336. SaveFocusedList()->Insert(0, *FocusedForm());
  337. *FocusedForm() = Form;
  338. AStorage->FocusWindowList = DisableTaskWindows(0);
  339. Form->Show();
  340. SendMessage(Form->Handle, CM_ACTIVATE, 0, 0);
  341. Storage = AStorage;
  342. }
  343. //---------------------------------------------------------------------------
  344. void __fastcall HideAsModal(TForm * Form, void *& Storage)
  345. {
  346. assert((static_cast<TPublicForm*>(Form))->FFormState.Contains(fsModal));
  347. TShowAsModalStorage * AStorage = static_cast<TShowAsModalStorage *>(Storage);
  348. Storage = NULL;
  349. SendMessage(Form->Handle, CM_DEACTIVATE, 0, 0);
  350. if (GetActiveWindow() != Form->Handle)
  351. {
  352. AStorage->FocusActiveWindow = 0;
  353. }
  354. Form->Hide();
  355. EnableTaskWindows(AStorage->FocusWindowList);
  356. TList * ASaveFocusedList = SaveFocusedList();
  357. TCustomForm ** AFocusedForm = FocusedForm();
  358. if (ASaveFocusedList->Count > 0)
  359. {
  360. *AFocusedForm = static_cast<TCustomForm *>(ASaveFocusedList->First());
  361. ASaveFocusedList->Remove(*AFocusedForm);
  362. }
  363. else
  364. {
  365. *AFocusedForm = NULL;
  366. }
  367. if (AStorage->FocusActiveWindow != 0)
  368. {
  369. SetActiveWindow(AStorage->FocusActiveWindow);
  370. }
  371. RestoreFocusState(AStorage->FocusState);
  372. (static_cast<TPublicForm*>(Form))->FFormState >> fsModal;
  373. delete AStorage;
  374. }
  375. //---------------------------------------------------------------------------
  376. void __fastcall ReleaseAsModal(TForm * Form, void *& Storage)
  377. {
  378. if (Storage != NULL)
  379. {
  380. HideAsModal(Form, Storage);
  381. }
  382. }
  383. //---------------------------------------------------------------------------
  384. bool __fastcall SelectDirectory(AnsiString & Path, const AnsiString Prompt,
  385. bool PreserveFileName)
  386. {
  387. bool Result;
  388. unsigned int ErrorMode;
  389. ErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
  390. try
  391. {
  392. AnsiString Directory;
  393. AnsiString FileName;
  394. if (!PreserveFileName || DirectoryExists(Path))
  395. {
  396. Directory = Path;
  397. }
  398. else
  399. {
  400. Directory = ExtractFilePath(Path);
  401. FileName = ExtractFileName(Path);
  402. }
  403. Result = SelectDirectory(Prompt, "", Directory);
  404. if (Result)
  405. {
  406. Path = Directory;
  407. if (!FileName.IsEmpty())
  408. {
  409. Path = IncludeTrailingBackslash(Path) + FileName;
  410. }
  411. }
  412. }
  413. __finally
  414. {
  415. SetErrorMode(ErrorMode);
  416. }
  417. return Result;
  418. }
  419. //---------------------------------------------------------------------------
  420. bool __fastcall ListViewAnyChecked(TListView * ListView, bool Checked)
  421. {
  422. bool AnyChecked = false;
  423. for (int Index = 0; Index < ListView->Items->Count; Index++)
  424. {
  425. if (ListView->Items->Item[Index]->Checked == Checked)
  426. {
  427. AnyChecked = true;
  428. break;
  429. }
  430. }
  431. return AnyChecked;
  432. }
  433. //---------------------------------------------------------------------------
  434. void __fastcall ListViewCheckAll(TListView * ListView,
  435. TListViewCheckAll CheckAll)
  436. {
  437. bool Check;
  438. if (CheckAll == caToggle)
  439. {
  440. Check = ListViewAnyChecked(ListView, false);
  441. }
  442. else
  443. {
  444. Check = (CheckAll == caCheck);
  445. }
  446. for (int Index = 0; Index < ListView->Items->Count; Index++)
  447. {
  448. ListView->Items->Item[Index]->Checked = Check;
  449. }
  450. }
  451. //---------------------------------------------------------------------------
  452. // Windows algorithm is as follows (tested on W2k):
  453. // right:
  454. // is_delimiter(current)
  455. // false:
  456. // right(left(current) + 1)
  457. // true:
  458. // right(right(current) + 1)
  459. // left:
  460. // right(left(current) + 1)
  461. int CALLBACK PathWordBreakProc(char * Ch, int Current, int Len, int Code)
  462. {
  463. char Delimiters[] = "\\/ ;,.";
  464. int Result;
  465. AnsiString ACh;
  466. // stupid unicode autodetection
  467. // (on WinXP (or rather for RichEdit 2.0) we get unicode on input)
  468. if ((Len > 1) && (Ch[1] == '\0'))
  469. {
  470. // this convertes the unicode to ansi
  471. ACh = (wchar_t*)Ch;
  472. }
  473. else
  474. {
  475. ACh = Ch;
  476. }
  477. if (Code == WB_ISDELIMITER)
  478. {
  479. // we return negacy of what WinAPI docs says
  480. Result = (strchr(Delimiters, ACh[Current + 1]) == NULL);
  481. }
  482. else if (Code == WB_LEFT)
  483. {
  484. Result = ACh.SubString(1, Current - 1).LastDelimiter(Delimiters);
  485. }
  486. else if (Code == WB_RIGHT)
  487. {
  488. if (Current == 0)
  489. {
  490. // will be called gain with Current == 1
  491. Result = 0;
  492. }
  493. else
  494. {
  495. const char * P = strpbrk(ACh.c_str() + Current - 1, Delimiters);
  496. if (P == NULL)
  497. {
  498. Result = Len;
  499. }
  500. else
  501. {
  502. Result = P - ACh.c_str() + 1;
  503. }
  504. }
  505. }
  506. else
  507. {
  508. assert(false);
  509. Result = 0;
  510. }
  511. return Result;
  512. }
  513. //---------------------------------------------------------------------------
  514. class TPublicCustomCombo : public TCustomCombo
  515. {
  516. friend void __fastcall InstallPathWordBreakProc(TWinControl * Control);
  517. };
  518. //---------------------------------------------------------------------------
  519. void __fastcall InstallPathWordBreakProc(TWinControl * Control)
  520. {
  521. HWND Wnd;
  522. if (dynamic_cast<TCustomCombo*>(Control) != NULL)
  523. {
  524. TPublicCustomCombo * Combo =
  525. static_cast<TPublicCustomCombo *>(dynamic_cast<TCustomCombo *>(Control));
  526. Combo->HandleNeeded();
  527. Wnd = Combo->EditHandle;
  528. }
  529. else
  530. {
  531. Wnd = Control->Handle;
  532. }
  533. SendMessage(Wnd, EM_SETWORDBREAKPROC, 0, (LPARAM)(EDITWORDBREAKPROC)PathWordBreakProc);
  534. }
  535. //---------------------------------------------------------------------------
  536. static void __fastcall RemoveHiddenControlsFromOrder(TControl ** ControlsOrder, int & Count)
  537. {
  538. int Shift = 0;
  539. for (int Index = 0; Index < Count; Index++)
  540. {
  541. if (ControlsOrder[Index]->Visible)
  542. {
  543. ControlsOrder[Index - Shift] = ControlsOrder[Index];
  544. }
  545. else
  546. {
  547. Shift++;
  548. }
  549. }
  550. Count -= Shift;
  551. }
  552. //---------------------------------------------------------------------------
  553. void __fastcall RepaintStatusBar(TCustomStatusBar * StatusBar)
  554. {
  555. StatusBar->SimplePanel = !StatusBar->SimplePanel;
  556. StatusBar->SimplePanel = !StatusBar->SimplePanel;
  557. }
  558. //---------------------------------------------------------------------------
  559. void __fastcall SetVerticalControlsOrder(TControl ** ControlsOrder, int Count)
  560. {
  561. RemoveHiddenControlsFromOrder(ControlsOrder, Count);
  562. if (Count > 0)
  563. {
  564. TWinControl * CommonParent = ControlsOrder[0]->Parent;
  565. CommonParent->DisableAlign();
  566. try
  567. {
  568. int Top = 0;
  569. for (int Index = 0; Index < Count; Index++)
  570. {
  571. assert(ControlsOrder[Index]->Parent == CommonParent);
  572. if ((Index == 0) || (Top > ControlsOrder[Index]->Top))
  573. {
  574. Top = ControlsOrder[Index]->Top;
  575. }
  576. }
  577. for (int Index = 0; Index < Count; Index++)
  578. {
  579. ControlsOrder[Index]->Top = Top;
  580. Top += ControlsOrder[Index]->Height;
  581. }
  582. }
  583. __finally
  584. {
  585. CommonParent->EnableAlign();
  586. }
  587. }
  588. }
  589. //---------------------------------------------------------------------------
  590. void __fastcall SetHorizontalControlsOrder(TControl ** ControlsOrder, int Count)
  591. {
  592. RemoveHiddenControlsFromOrder(ControlsOrder, Count);
  593. if (Count > 0)
  594. {
  595. TWinControl * CommonParent = ControlsOrder[0]->Parent;
  596. CommonParent->DisableAlign();
  597. try
  598. {
  599. int Left = 0;
  600. for (int Index = 0; Index < Count; Index++)
  601. {
  602. assert(ControlsOrder[Index]->Parent == CommonParent);
  603. if ((Index == 0) || (Left > ControlsOrder[Index]->Left))
  604. {
  605. Left = ControlsOrder[Index]->Left;
  606. }
  607. }
  608. for (int Index = 0; Index < Count; Index++)
  609. {
  610. ControlsOrder[Index]->Left = Left;
  611. Left += ControlsOrder[Index]->Width;
  612. }
  613. }
  614. __finally
  615. {
  616. CommonParent->EnableAlign();
  617. }
  618. }
  619. }
  620. //---------------------------------------------------------------------------
  621. TPoint __fastcall GetAveCharSize(TCanvas* Canvas)
  622. {
  623. Integer I;
  624. Char Buffer[52];
  625. TSize Result;
  626. for (I = 0; I <= 25; I++) Buffer[I] = (Char)('A' + I);
  627. for (I = 0; I <= 25; I++) Buffer[I+26] = (Char)('a' + I);
  628. GetTextExtentPoint(Canvas->Handle, Buffer, 52, &Result);
  629. return TPoint(Result.cx / 52, Result.cy);
  630. }
  631. //---------------------------------------------------------------------------
  632. void __fastcall MakeNextInTabOrder(TWinControl * Control, TWinControl * After)
  633. {
  634. if (After->TabOrder > Control->TabOrder)
  635. {
  636. After->TabOrder = Control->TabOrder;
  637. }
  638. else if (After->TabOrder < Control->TabOrder - 1)
  639. {
  640. After->TabOrder = static_cast<TTabOrder>(Control->TabOrder - 1);
  641. }
  642. }
  643. //---------------------------------------------------------------------------
  644. void __fastcall CutFormToDesktop(TForm * Form)
  645. {
  646. assert(Form->Monitor != NULL);
  647. TRect Workarea = Form->Monitor->WorkareaRect;
  648. if (Form->Top + Form->Height > Workarea.Bottom)
  649. {
  650. Form->Height = Workarea.Bottom - Form->Top;
  651. }
  652. if (Form->Left + Form->Width >= Workarea.Right)
  653. {
  654. Form->Width = Workarea.Right - Form->Left;
  655. }
  656. }
  657. //---------------------------------------------------------------------------
  658. void __fastcall UpdateFormPosition(TForm * Form, TPosition Position)
  659. {
  660. if ((Position == poScreenCenter) ||
  661. (Position == poOwnerFormCenter) ||
  662. (Position == poMainFormCenter))
  663. {
  664. TCustomForm * CenterForm = NULL;
  665. if ((Position == poOwnerFormCenter) ||
  666. (Position == poMainFormCenter))
  667. {
  668. CenterForm = Application->MainForm;
  669. if ((Position == poOwnerFormCenter) &&
  670. (dynamic_cast<TCustomForm*>(Form->Owner) != NULL))
  671. {
  672. CenterForm = dynamic_cast<TCustomForm*>(Form->Owner);
  673. }
  674. }
  675. int X, Y;
  676. if (CenterForm != NULL)
  677. {
  678. X = ((((TForm *)CenterForm)->Width - Form->Width) / 2) +
  679. ((TForm *)CenterForm)->Left;
  680. Y = ((((TForm *)CenterForm)->Height - Form->Height) / 2) +
  681. ((TForm *)CenterForm)->Top;
  682. }
  683. else
  684. {
  685. X = (Screen->Width - Form->Width) / 2;
  686. Y = (Screen->Height - Form->Height) / 2;
  687. }
  688. if (X < 0)
  689. {
  690. X = 0;
  691. }
  692. if (Y < 0)
  693. {
  694. Y = 0;
  695. }
  696. Form->SetBounds(X, Y, Form->Width, Form->Height);
  697. }
  698. }
  699. //---------------------------------------------------------------------------
  700. void __fastcall ResizeForm(TForm * Form, int Width, int Height)
  701. {
  702. if (Height > Screen->WorkAreaHeight)
  703. {
  704. Height = Screen->WorkAreaHeight;
  705. }
  706. if (Width > Screen->WorkAreaWidth)
  707. {
  708. Width = Screen->WorkAreaWidth;
  709. }
  710. if (Height < Form->Constraints->MinHeight)
  711. {
  712. Height = Form->Constraints->MinHeight;
  713. }
  714. if (Width < Form->Constraints->MinWidth)
  715. {
  716. Width = Form->Constraints->MinWidth;
  717. }
  718. int Top = Form->Top + ((Form->Height - Height) / 2);
  719. int Left = Form->Left + ((Form->Width - Width) / 2);
  720. if (Top + Height > Screen->WorkAreaTop + Screen->WorkAreaHeight)
  721. {
  722. Top = Screen->WorkAreaTop + Screen->WorkAreaHeight - Height;
  723. }
  724. if (Left + Width >= Screen->WorkAreaLeft + Screen->WorkAreaWidth)
  725. {
  726. Left = Screen->WorkAreaLeft + Screen->WorkAreaWidth - Width;
  727. }
  728. if (Top < 0)
  729. {
  730. Top = 0;
  731. }
  732. if (Left < 0)
  733. {
  734. Left = 0;
  735. }
  736. Form->SetBounds(Left, Top, Width, Height);
  737. // due to constraints, form can remain larger, make sure it is centered although
  738. Left = Form->Left + ((Width - Form->Width) / 2);
  739. Top = Form->Top + ((Height - Form->Height) / 2);
  740. Form->SetBounds(Left, Top, Width, Height);
  741. }
  742. //---------------------------------------------------------------------------
  743. void __fastcall SetCorrectFormParent(TForm * Form)
  744. {
  745. try
  746. {
  747. // Kind of hack (i do not understand this much).
  748. // Rationale: for example when the preferences window is opened from login dialog
  749. // settings Parent to Screen->ActiveForm leads to "cannot focus disabled control",
  750. // so we set Parent only when absolutelly necessary
  751. // (dialog opened from log window or editor)
  752. // TODO: does not work for dialogs opened from preferences dialog
  753. if ((Application->MainForm != NULL) &&
  754. (Application->MainForm != Screen->ActiveForm))
  755. {
  756. // this should better be check for modal form
  757. AnsiString C = Screen->ActiveForm->Caption;
  758. if ((Screen->ActiveForm != NULL) &&
  759. (Screen->ActiveForm->BorderStyle != bsDialog))
  760. {
  761. Form->ParentWindow = Screen->ActiveForm->Handle;
  762. }
  763. }
  764. }
  765. catch(...)
  766. {
  767. // avoid any errors, however we want to know about this in debug version.
  768. #ifdef _DEBUG
  769. throw;
  770. #endif
  771. }
  772. }
  773. //---------------------------------------------------------------------------
  774. void __fastcall InvokeHelp(TWinControl * Control)
  775. {
  776. assert(Control != NULL);
  777. HELPINFO HelpInfo;
  778. HelpInfo.cbSize = sizeof(HelpInfo);
  779. HelpInfo.iContextType = HELPINFO_WINDOW;
  780. HelpInfo.iCtrlId = 0;
  781. HelpInfo.hItemHandle = Control->Handle;
  782. HelpInfo.dwContextId = 0;
  783. HelpInfo.MousePos.x = 0;
  784. HelpInfo.MousePos.y = 0;
  785. SendMessage(Control->Handle, WM_HELP, NULL, reinterpret_cast<long>(&HelpInfo));
  786. }
  787. //---------------------------------------------------------------------------
  788. //---------------------------------------------------------------------------
  789. static void __fastcall FocusableLabelCanvas(TStaticText * StaticText,
  790. TControlCanvas ** ACanvas, TRect & R)
  791. {
  792. TControlCanvas * Canvas = new TControlCanvas();
  793. try
  794. {
  795. Canvas->Control = StaticText;
  796. R = StaticText->ClientRect;
  797. AnsiString Caption = StaticText->Caption;
  798. bool AccelChar = false;
  799. if (StaticText->ShowAccelChar)
  800. {
  801. Caption = StripHotkey(Caption);
  802. AccelChar = (Caption != StaticText->Caption);
  803. }
  804. TSize TextSize = Canvas->TextExtent(Caption);
  805. assert(StaticText->BorderStyle == sbsNone); // not taken into account
  806. if (AccelChar)
  807. {
  808. TextSize.cy += 2;
  809. }
  810. R.Bottom = R.Top + TextSize.cy;
  811. if (StaticText->Alignment == taRightJustify)
  812. {
  813. R.Left = R.Right - TextSize.cx;
  814. }
  815. else
  816. {
  817. R.Right = R.Left + TextSize.cx;
  818. }
  819. }
  820. __finally
  821. {
  822. if (ACanvas == NULL)
  823. {
  824. delete Canvas;
  825. }
  826. }
  827. if (ACanvas != NULL)
  828. {
  829. *ACanvas = Canvas;
  830. }
  831. }
  832. //---------------------------------------------------------------------------
  833. static void __fastcall FocusableLabelWindowProc(void * Data, TMessage & Message,
  834. bool & Clicked)
  835. {
  836. Clicked = false;
  837. TStaticText * StaticText = static_cast<TStaticText *>(Data);
  838. if (Message.Msg == WM_LBUTTONDOWN)
  839. {
  840. StaticText->SetFocus();
  841. // in case the action takes long, make sure focus is shown immediatelly
  842. UpdateWindow(StaticText->Handle);
  843. Clicked = true;
  844. Message.Result = 1;
  845. }
  846. else if (Message.Msg == WM_RBUTTONDOWN)
  847. {
  848. StaticText->SetFocus();
  849. Message.Result = 1;
  850. }
  851. else if (Message.Msg == WM_CHAR)
  852. {
  853. if (reinterpret_cast<TWMChar &>(Message).CharCode == ' ')
  854. {
  855. Clicked = true;
  856. Message.Result = 1;
  857. }
  858. else
  859. {
  860. ControlWndProc(StaticText)(Message);
  861. }
  862. }
  863. else if (Message.Msg == CM_DIALOGCHAR)
  864. {
  865. if (StaticText->CanFocus() && StaticText->ShowAccelChar &&
  866. IsAccel(reinterpret_cast<TCMDialogChar &>(Message).CharCode, StaticText->Caption))
  867. {
  868. StaticText->SetFocus();
  869. // in case the action takes long, make sure focus is shown immediatelly
  870. UpdateWindow(StaticText->Handle);
  871. Clicked = true;
  872. Message.Result = 1;
  873. }
  874. else
  875. {
  876. ControlWndProc(StaticText)(Message);
  877. }
  878. }
  879. else
  880. {
  881. ControlWndProc(StaticText)(Message);
  882. }
  883. if (Message.Msg == WM_PAINT)
  884. {
  885. TRect R;
  886. TControlCanvas * Canvas;
  887. FocusableLabelCanvas(StaticText, &Canvas, R);
  888. try
  889. {
  890. if (StaticText->Focused())
  891. {
  892. Canvas->DrawFocusRect(R);
  893. }
  894. else if (!StaticText->Font->Style.Contains(fsUnderline))
  895. {
  896. Canvas->Pen->Style = psDot;
  897. Canvas->Brush->Style = bsClear;
  898. if (!StaticText->Enabled)
  899. {
  900. Canvas->Pen->Color = clBtnHighlight;
  901. Canvas->MoveTo(R.Left + 1 + 1, R.Bottom);
  902. Canvas->LineTo(R.Right + 1, R.Bottom);
  903. Canvas->Pen->Color = clGrayText;
  904. }
  905. Canvas->MoveTo(R.Left + 1, R.Bottom - 1);
  906. Canvas->LineTo(R.Right, R.Bottom - 1);
  907. }
  908. }
  909. __finally
  910. {
  911. delete Canvas;
  912. }
  913. }
  914. else if ((Message.Msg == WM_SETFOCUS) || (Message.Msg == WM_KILLFOCUS) ||
  915. (Message.Msg == CM_ENABLEDCHANGED))
  916. {
  917. StaticText->Invalidate();
  918. }
  919. }
  920. //---------------------------------------------------------------------------
  921. static THintWindow * PersistentHintWindow = NULL;
  922. static TControl * PersistentHintControl = NULL;
  923. //---------------------------------------------------------------------------
  924. void __fastcall CancelPersistentHint()
  925. {
  926. if (PersistentHintWindow != NULL)
  927. {
  928. PersistentHintControl = NULL;
  929. SAFE_DESTROY(PersistentHintWindow);
  930. }
  931. }
  932. //---------------------------------------------------------------------------
  933. void __fastcall ShowPersistentHint(TControl * Control, TPoint HintPos)
  934. {
  935. CancelPersistentHint();
  936. THintInfo HintInfo;
  937. HintInfo.HintControl = Control;
  938. HintInfo.HintPos = HintPos;
  939. HintInfo.HintMaxWidth = Screen->Width;
  940. HintInfo.HintColor = Application->HintColor;
  941. HintInfo.HintStr = GetShortHint(Control->Hint);
  942. HintInfo.HintData = NULL;
  943. bool CanShow = true;
  944. if (Application->OnShowHint != NULL)
  945. {
  946. Application->OnShowHint(HintInfo.HintStr, CanShow, HintInfo);
  947. }
  948. if (CanShow)
  949. {
  950. PersistentHintControl = Control;
  951. PersistentHintWindow = new THintWindow(Application);
  952. PersistentHintWindow->BiDiMode = Control->BiDiMode;
  953. PersistentHintWindow->Color = HintInfo.HintColor;
  954. TRect HintWinRect;
  955. if (HintInfo.HintMaxWidth < Control->Width)
  956. {
  957. HintInfo.HintMaxWidth = Control->Width;
  958. }
  959. HintWinRect = PersistentHintWindow->CalcHintRect(
  960. HintInfo.HintMaxWidth, HintInfo.HintStr, HintInfo.HintData);
  961. OffsetRect(HintWinRect, HintInfo.HintPos.x, HintInfo.HintPos.y);
  962. // TODO: right align window placement for UseRightToLeftAlignment, see Forms.pas
  963. PersistentHintWindow->ActivateHintData(HintWinRect, HintInfo.HintStr, HintInfo.HintData);
  964. }
  965. }
  966. //---------------------------------------------------------------------------
  967. static void __fastcall HintLabelWindowProc(void * Data, TMessage & Message)
  968. {
  969. bool Clicked = false;
  970. bool Cancel = false;
  971. TStaticText * StaticText = static_cast<TStaticText *>(Data);
  972. if (Message.Msg == CM_HINTSHOW)
  973. {
  974. TCMHintShow & HintShow = reinterpret_cast<TCMHintShow &>(Message);
  975. if (PersistentHintControl == StaticText)
  976. {
  977. // do not allow standard hint when persistent is already shown
  978. HintShow.Result = 1;
  979. }
  980. else
  981. {
  982. HintShow.HintInfo->HideTimeout = 100000; // never
  983. }
  984. }
  985. else if (Message.Msg == CN_KEYDOWN)
  986. {
  987. if ((reinterpret_cast<TWMKey &>(Message).CharCode == VK_ESCAPE) &&
  988. (PersistentHintControl == StaticText))
  989. {
  990. CancelPersistentHint();
  991. StaticText->Invalidate();
  992. Message.Result = 1;
  993. }
  994. else
  995. {
  996. FocusableLabelWindowProc(Data, Message, Clicked);
  997. }
  998. }
  999. else
  1000. {
  1001. FocusableLabelWindowProc(Data, Message, Clicked);
  1002. }
  1003. if (Message.Msg == CM_CANCELMODE)
  1004. {
  1005. TCMCancelMode & CancelMessage = (TCMCancelMode&)Message;
  1006. if ((CancelMessage.Sender != StaticText) &&
  1007. (CancelMessage.Sender != PersistentHintWindow))
  1008. {
  1009. Cancel = true;
  1010. }
  1011. }
  1012. if ((Message.Msg == WM_DESTROY) || (Message.Msg == WM_KILLFOCUS))
  1013. {
  1014. Cancel = true;
  1015. }
  1016. if (Cancel && (PersistentHintControl == StaticText))
  1017. {
  1018. CancelPersistentHint();
  1019. }
  1020. if (Clicked && (PersistentHintControl != StaticText))
  1021. {
  1022. TRect R;
  1023. TPoint HintPos;
  1024. FocusableLabelCanvas(StaticText, NULL, R);
  1025. HintPos.y = R.Bottom - R.Top;
  1026. HintPos.x = R.Left;
  1027. ShowPersistentHint(StaticText, StaticText->ClientToScreen(HintPos));
  1028. }
  1029. }
  1030. //---------------------------------------------------------------------------
  1031. void __fastcall HintLabel(TStaticText * StaticText, AnsiString Hint)
  1032. {
  1033. StaticText->ParentFont = true;
  1034. if (!Hint.IsEmpty())
  1035. {
  1036. StaticText->Hint = Hint;
  1037. }
  1038. StaticText->ShowHint = true;
  1039. StaticText->Cursor = crHandPoint;
  1040. TWndMethod WindowProc;
  1041. ((TMethod*)&WindowProc)->Data = StaticText;
  1042. ((TMethod*)&WindowProc)->Code = HintLabelWindowProc;
  1043. StaticText->WindowProc = WindowProc;
  1044. }
  1045. //---------------------------------------------------------------------------
  1046. void __fastcall HintLabelRestore(TStaticText * StaticText)
  1047. {
  1048. StaticText->WindowProc = ControlWndProc(StaticText);
  1049. StaticText->ShowHint = false;
  1050. StaticText->Cursor = crDefault;
  1051. }
  1052. //---------------------------------------------------------------------------
  1053. static void __fastcall LinkLabelClick(TStaticText * StaticText)
  1054. {
  1055. if (StaticText->OnClick != NULL)
  1056. {
  1057. StaticText->OnClick(StaticText);
  1058. }
  1059. else
  1060. {
  1061. AnsiString Url = StaticText->Caption;
  1062. if (!SameText(Url.SubString(1, 4), "http") && (Url.Pos("@") > 0))
  1063. {
  1064. Url = "mailto:" + Url;
  1065. }
  1066. OpenBrowser(Url);
  1067. }
  1068. }
  1069. //---------------------------------------------------------------------------
  1070. static void __fastcall LinkLabelWindowProc(void * Data, TMessage & Message)
  1071. {
  1072. bool Clicked = false;
  1073. TStaticText * StaticText = static_cast<TStaticText *>(Data);
  1074. if (Message.Msg == WM_CONTEXTMENU)
  1075. {
  1076. TWMContextMenu & ContextMenu = reinterpret_cast<TWMContextMenu &>(Message);
  1077. if ((ContextMenu.Pos.x < 0) && (ContextMenu.Pos.y < 0))
  1078. {
  1079. TRect R;
  1080. FocusableLabelCanvas(StaticText, NULL, R);
  1081. TPoint P = StaticText->ClientToScreen(TPoint(R.Left, R.Bottom));
  1082. ContextMenu.Pos.x = static_cast<short>(P.x);
  1083. ContextMenu.Pos.y = static_cast<short>(P.y);
  1084. }
  1085. }
  1086. else if (Message.Msg == WM_KEYDOWN)
  1087. {
  1088. TWMKey & Key = reinterpret_cast<TWMKey &>(Message);
  1089. if ((GetKeyState(VK_CONTROL) < 0) && (Key.CharCode == 'C'))
  1090. {
  1091. CopyToClipboard(StaticText->Caption);
  1092. Message.Result = 1;
  1093. }
  1094. else
  1095. {
  1096. FocusableLabelWindowProc(Data, Message, Clicked);
  1097. }
  1098. }
  1099. FocusableLabelWindowProc(Data, Message, Clicked);
  1100. if (Message.Msg == WM_DESTROY)
  1101. {
  1102. delete StaticText->PopupMenu;
  1103. assert(StaticText->PopupMenu == NULL);
  1104. }
  1105. if (Clicked)
  1106. {
  1107. LinkLabelClick(StaticText);
  1108. }
  1109. }
  1110. //---------------------------------------------------------------------------
  1111. static void __fastcall LinkLabelContextMenuClick(void * Data, TObject * Sender)
  1112. {
  1113. TStaticText * StaticText = static_cast<TStaticText *>(Data);
  1114. TMenuItem * MenuItem = dynamic_cast<TMenuItem *>(Sender);
  1115. assert(MenuItem != NULL);
  1116. if (MenuItem->Tag == 0)
  1117. {
  1118. LinkLabelClick(StaticText);
  1119. }
  1120. else
  1121. {
  1122. CopyToClipboard(StaticText->Caption);
  1123. }
  1124. }
  1125. //---------------------------------------------------------------------------
  1126. void __fastcall LinkLabel(TStaticText * StaticText, AnsiString Url,
  1127. TNotifyEvent OnEnter)
  1128. {
  1129. StaticText->ParentFont = true;
  1130. StaticText->Font->Style = StaticText->Font->Style << fsUnderline;
  1131. StaticText->Font->Color = clBlue;
  1132. StaticText->Cursor = crHandPoint;
  1133. reinterpret_cast<TButton*>(StaticText)->OnEnter = OnEnter;
  1134. if (!Url.IsEmpty())
  1135. {
  1136. StaticText->Caption = Url;
  1137. }
  1138. if (StaticText->OnClick == NULL)
  1139. {
  1140. assert(StaticText->PopupMenu == NULL);
  1141. StaticText->PopupMenu = new TPopupMenu(StaticText);
  1142. try
  1143. {
  1144. TNotifyEvent ContextMenuOnClick;
  1145. ((TMethod*)&ContextMenuOnClick)->Data = StaticText;
  1146. ((TMethod*)&ContextMenuOnClick)->Code = LinkLabelContextMenuClick;
  1147. TMenuItem * Item;
  1148. Item = new TMenuItem(StaticText->PopupMenu);
  1149. Item->Caption = LoadStr(URL_LINK_OPEN);
  1150. Item->Tag = 0;
  1151. Item->ShortCut = ShortCut(' ', TShiftState());
  1152. Item->OnClick = ContextMenuOnClick;
  1153. StaticText->PopupMenu->Items->Add(Item);
  1154. Item = new TMenuItem(StaticText->PopupMenu);
  1155. Item->Caption = LoadStr(URL_LINK_COPY);
  1156. Item->Tag = 1;
  1157. Item->ShortCut = ShortCut('C', TShiftState() << ssCtrl);
  1158. Item->OnClick = ContextMenuOnClick;
  1159. StaticText->PopupMenu->Items->Add(Item);
  1160. }
  1161. catch(...)
  1162. {
  1163. delete StaticText->PopupMenu;
  1164. assert(StaticText->PopupMenu == NULL);
  1165. throw;
  1166. }
  1167. }
  1168. TWndMethod WindowProc;
  1169. ((TMethod*)&WindowProc)->Data = StaticText;
  1170. ((TMethod*)&WindowProc)->Code = LinkLabelWindowProc;
  1171. StaticText->WindowProc = WindowProc;
  1172. }
  1173. //---------------------------------------------------------------------------
  1174. int __fastcall SafeShowModal(TForm * Form)
  1175. {
  1176. // FIX: Due to some bug in Theme Manager, certain forms randomly
  1177. // fails in call to ShowModal(), hence repeat the call until it succeeds.
  1178. int Result = -1;
  1179. int Retry = 0;
  1180. do
  1181. {
  1182. try
  1183. {
  1184. Result = Form->ShowModal();
  1185. }
  1186. catch (EOSError & E)
  1187. {
  1188. if (E.Message == Sysconst_SUnkOSError)
  1189. {
  1190. ++Retry;
  1191. if (Retry >= 10)
  1192. {
  1193. throw;
  1194. }
  1195. else
  1196. {
  1197. Form->Visible = false;
  1198. }
  1199. }
  1200. else
  1201. {
  1202. throw;
  1203. }
  1204. }
  1205. }
  1206. while (Result < 0);
  1207. return Result;
  1208. }
  1209. //---------------------------------------------------------------------------
  1210. static void __fastcall CreateHandles(TWinControl * Control)
  1211. {
  1212. Control->HandleNeeded();
  1213. for (int Index = 0; Index < Control->ControlCount; Index++)
  1214. {
  1215. TWinControl * ChildControl = dynamic_cast<TWinControl *>(Control->Controls[Index]);
  1216. if (ChildControl != NULL)
  1217. {
  1218. CreateHandles(ChildControl);
  1219. }
  1220. }
  1221. }
  1222. //---------------------------------------------------------------------------
  1223. TForm * __fastcall _SafeFormValidate(TForm * Form, int & Retry)
  1224. {
  1225. try
  1226. {
  1227. CreateHandles(Form);
  1228. }
  1229. catch (EOSError & E)
  1230. {
  1231. delete Form;
  1232. Form = NULL;
  1233. ++Retry;
  1234. if ((E.Message != Sysconst_SUnkOSError) ||
  1235. (Retry >= 10))
  1236. {
  1237. throw;
  1238. }
  1239. }
  1240. catch(...)
  1241. {
  1242. delete Form;
  1243. }
  1244. return Form;
  1245. }