VCLCommon.cpp 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295
  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. };
  314. //---------------------------------------------------------------------------
  315. void __fastcall ShowAsModal(TForm * Form, void *& Storage)
  316. {
  317. SetCorrectFormParent(Form);
  318. CancelDrag();
  319. if (GetCapture() != 0) SendMessage(GetCapture(), WM_CANCELMODE, 0, 0);
  320. ReleaseCapture();
  321. (static_cast<TPublicForm*>(Form))->FFormState << fsModal;
  322. TShowAsModalStorage * AStorage = new TShowAsModalStorage;
  323. AStorage->FocusActiveWindow = GetActiveWindow();
  324. AStorage->FocusWindowList = DisableTaskWindows(0);
  325. Form->Show();
  326. SendMessage(Form->Handle, CM_ACTIVATE, 0, 0);
  327. Storage = AStorage;
  328. }
  329. //---------------------------------------------------------------------------
  330. void __fastcall HideAsModal(TForm * Form, void *& Storage)
  331. {
  332. assert((static_cast<TPublicForm*>(Form))->FFormState.Contains(fsModal));
  333. TShowAsModalStorage * AStorage = static_cast<TShowAsModalStorage *>(Storage);
  334. Storage = NULL;
  335. SendMessage(Form->Handle, CM_DEACTIVATE, 0, 0);
  336. if (GetActiveWindow() != Form->Handle)
  337. {
  338. AStorage->FocusActiveWindow = 0;
  339. }
  340. Form->Hide();
  341. EnableTaskWindows(AStorage->FocusWindowList);
  342. if (AStorage->FocusActiveWindow != 0)
  343. {
  344. SetActiveWindow(AStorage->FocusActiveWindow);
  345. }
  346. (static_cast<TPublicForm*>(Form))->FFormState >> fsModal;
  347. delete AStorage;
  348. }
  349. //---------------------------------------------------------------------------
  350. void __fastcall ReleaseAsModal(TForm * Form, void *& Storage)
  351. {
  352. if (Storage != NULL)
  353. {
  354. HideAsModal(Form, Storage);
  355. }
  356. }
  357. //---------------------------------------------------------------------------
  358. bool __fastcall SelectDirectory(AnsiString & Path, const AnsiString Prompt,
  359. bool PreserveFileName)
  360. {
  361. bool Result;
  362. unsigned int ErrorMode;
  363. ErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
  364. try
  365. {
  366. AnsiString Directory;
  367. AnsiString FileName;
  368. if (!PreserveFileName || DirectoryExists(Path))
  369. {
  370. Directory = Path;
  371. }
  372. else
  373. {
  374. Directory = ExtractFilePath(Path);
  375. FileName = ExtractFileName(Path);
  376. }
  377. Result = SelectDirectory(Prompt, "", Directory);
  378. if (Result)
  379. {
  380. Path = Directory;
  381. if (!FileName.IsEmpty())
  382. {
  383. Path = IncludeTrailingBackslash(Path) + FileName;
  384. }
  385. }
  386. }
  387. __finally
  388. {
  389. SetErrorMode(ErrorMode);
  390. }
  391. return Result;
  392. }
  393. //---------------------------------------------------------------------------
  394. bool __fastcall ListViewAnyChecked(TListView * ListView, bool Checked)
  395. {
  396. bool AnyChecked = false;
  397. for (int Index = 0; Index < ListView->Items->Count; Index++)
  398. {
  399. if (ListView->Items->Item[Index]->Checked == Checked)
  400. {
  401. AnyChecked = true;
  402. break;
  403. }
  404. }
  405. return AnyChecked;
  406. }
  407. //---------------------------------------------------------------------------
  408. void __fastcall ListViewCheckAll(TListView * ListView,
  409. TListViewCheckAll CheckAll)
  410. {
  411. bool Check;
  412. if (CheckAll == caToggle)
  413. {
  414. Check = ListViewAnyChecked(ListView, false);
  415. }
  416. else
  417. {
  418. Check = (CheckAll == caCheck);
  419. }
  420. for (int Index = 0; Index < ListView->Items->Count; Index++)
  421. {
  422. ListView->Items->Item[Index]->Checked = Check;
  423. }
  424. }
  425. //---------------------------------------------------------------------------
  426. // Windows algorithm is as follows (tested on W2k):
  427. // right:
  428. // is_delimiter(current)
  429. // false:
  430. // right(left(current) + 1)
  431. // true:
  432. // right(right(current) + 1)
  433. // left:
  434. // right(left(current) + 1)
  435. int CALLBACK PathWordBreakProc(char * Ch, int Current, int Len, int Code)
  436. {
  437. char Delimiters[] = "\\/ ;,.";
  438. int Result;
  439. AnsiString ACh;
  440. // stupid unicode autodetection
  441. // (on WinXP (or rather for RichEdit 2.0) we get unicode on input)
  442. if ((Len > 1) && (Ch[1] == '\0'))
  443. {
  444. // this convertes the unicode to ansi
  445. ACh = (wchar_t*)Ch;
  446. }
  447. else
  448. {
  449. ACh = Ch;
  450. }
  451. if (Code == WB_ISDELIMITER)
  452. {
  453. // we return negacy of what WinAPI docs says
  454. Result = (strchr(Delimiters, ACh[Current + 1]) == NULL);
  455. }
  456. else if (Code == WB_LEFT)
  457. {
  458. Result = ACh.SubString(1, Current - 1).LastDelimiter(Delimiters);
  459. }
  460. else if (Code == WB_RIGHT)
  461. {
  462. if (Current == 0)
  463. {
  464. // will be called gain with Current == 1
  465. Result = 0;
  466. }
  467. else
  468. {
  469. const char * P = strpbrk(ACh.c_str() + Current - 1, Delimiters);
  470. if (P == NULL)
  471. {
  472. Result = Len;
  473. }
  474. else
  475. {
  476. Result = P - ACh.c_str() + 1;
  477. }
  478. }
  479. }
  480. else
  481. {
  482. assert(false);
  483. Result = 0;
  484. }
  485. return Result;
  486. }
  487. //---------------------------------------------------------------------------
  488. class TPublicCustomCombo : public TCustomCombo
  489. {
  490. friend void __fastcall InstallPathWordBreakProc(TWinControl * Control);
  491. };
  492. //---------------------------------------------------------------------------
  493. void __fastcall InstallPathWordBreakProc(TWinControl * Control)
  494. {
  495. HWND Wnd;
  496. if (dynamic_cast<TCustomCombo*>(Control) != NULL)
  497. {
  498. TPublicCustomCombo * Combo =
  499. static_cast<TPublicCustomCombo *>(dynamic_cast<TCustomCombo *>(Control));
  500. Combo->HandleNeeded();
  501. Wnd = Combo->EditHandle;
  502. }
  503. else
  504. {
  505. Wnd = Control->Handle;
  506. }
  507. SendMessage(Wnd, EM_SETWORDBREAKPROC, 0, (LPARAM)(EDITWORDBREAKPROC)PathWordBreakProc);
  508. }
  509. //---------------------------------------------------------------------------
  510. static void __fastcall RemoveHiddenControlsFromOrder(TControl ** ControlsOrder, int & Count)
  511. {
  512. int Shift = 0;
  513. for (int Index = 0; Index < Count; Index++)
  514. {
  515. if (ControlsOrder[Index]->Visible)
  516. {
  517. ControlsOrder[Index - Shift] = ControlsOrder[Index];
  518. }
  519. else
  520. {
  521. Shift++;
  522. }
  523. }
  524. Count -= Shift;
  525. }
  526. //---------------------------------------------------------------------------
  527. void __fastcall RepaintStatusBar(TCustomStatusBar * StatusBar)
  528. {
  529. StatusBar->SimplePanel = !StatusBar->SimplePanel;
  530. StatusBar->SimplePanel = !StatusBar->SimplePanel;
  531. }
  532. //---------------------------------------------------------------------------
  533. void __fastcall SetVerticalControlsOrder(TControl ** ControlsOrder, int Count)
  534. {
  535. RemoveHiddenControlsFromOrder(ControlsOrder, Count);
  536. if (Count > 0)
  537. {
  538. TWinControl * CommonParent = ControlsOrder[0]->Parent;
  539. CommonParent->DisableAlign();
  540. try
  541. {
  542. int Top = 0;
  543. for (int Index = 0; Index < Count; Index++)
  544. {
  545. assert(ControlsOrder[Index]->Parent == CommonParent);
  546. if ((Index == 0) || (Top > ControlsOrder[Index]->Top))
  547. {
  548. Top = ControlsOrder[Index]->Top;
  549. }
  550. }
  551. for (int Index = 0; Index < Count; Index++)
  552. {
  553. ControlsOrder[Index]->Top = Top;
  554. Top += ControlsOrder[Index]->Height;
  555. }
  556. }
  557. __finally
  558. {
  559. CommonParent->EnableAlign();
  560. }
  561. }
  562. }
  563. //---------------------------------------------------------------------------
  564. void __fastcall SetHorizontalControlsOrder(TControl ** ControlsOrder, int Count)
  565. {
  566. RemoveHiddenControlsFromOrder(ControlsOrder, Count);
  567. if (Count > 0)
  568. {
  569. TWinControl * CommonParent = ControlsOrder[0]->Parent;
  570. CommonParent->DisableAlign();
  571. try
  572. {
  573. int Left = 0;
  574. for (int Index = 0; Index < Count; Index++)
  575. {
  576. assert(ControlsOrder[Index]->Parent == CommonParent);
  577. if ((Index == 0) || (Left > ControlsOrder[Index]->Left))
  578. {
  579. Left = ControlsOrder[Index]->Left;
  580. }
  581. }
  582. for (int Index = 0; Index < Count; Index++)
  583. {
  584. ControlsOrder[Index]->Left = Left;
  585. Left += ControlsOrder[Index]->Width;
  586. }
  587. }
  588. __finally
  589. {
  590. CommonParent->EnableAlign();
  591. }
  592. }
  593. }
  594. //---------------------------------------------------------------------------
  595. TPoint __fastcall GetAveCharSize(TCanvas* Canvas)
  596. {
  597. Integer I;
  598. Char Buffer[52];
  599. TSize Result;
  600. for (I = 0; I <= 25; I++) Buffer[I] = (Char)('A' + I);
  601. for (I = 0; I <= 25; I++) Buffer[I+26] = (Char)('a' + I);
  602. GetTextExtentPoint(Canvas->Handle, Buffer, 52, &Result);
  603. return TPoint(Result.cx / 52, Result.cy);
  604. }
  605. //---------------------------------------------------------------------------
  606. void __fastcall MakeNextInTabOrder(TWinControl * Control, TWinControl * After)
  607. {
  608. if (After->TabOrder > Control->TabOrder)
  609. {
  610. After->TabOrder = Control->TabOrder;
  611. }
  612. else if (After->TabOrder < Control->TabOrder - 1)
  613. {
  614. After->TabOrder = static_cast<TTabOrder>(Control->TabOrder - 1);
  615. }
  616. }
  617. //---------------------------------------------------------------------------
  618. void __fastcall CutFormToDesktop(TForm * Form)
  619. {
  620. assert(Form->Monitor != NULL);
  621. TRect Workarea = Form->Monitor->WorkareaRect;
  622. if (Form->Top + Form->Height > Workarea.Bottom)
  623. {
  624. Form->Height = Workarea.Bottom - Form->Top;
  625. }
  626. if (Form->Left + Form->Width >= Workarea.Right)
  627. {
  628. Form->Width = Workarea.Right - Form->Left;
  629. }
  630. }
  631. //---------------------------------------------------------------------------
  632. void __fastcall UpdateFormPosition(TForm * Form, TPosition Position)
  633. {
  634. if ((Position == poScreenCenter) ||
  635. (Position == poOwnerFormCenter) ||
  636. (Position == poMainFormCenter))
  637. {
  638. TCustomForm * CenterForm = NULL;
  639. if ((Position == poOwnerFormCenter) ||
  640. (Position == poMainFormCenter))
  641. {
  642. CenterForm = Application->MainForm;
  643. if ((Position == poOwnerFormCenter) &&
  644. (dynamic_cast<TCustomForm*>(Form->Owner) != NULL))
  645. {
  646. CenterForm = dynamic_cast<TCustomForm*>(Form->Owner);
  647. }
  648. }
  649. int X, Y;
  650. if (CenterForm != NULL)
  651. {
  652. X = ((((TForm *)CenterForm)->Width - Form->Width) / 2) +
  653. ((TForm *)CenterForm)->Left;
  654. Y = ((((TForm *)CenterForm)->Height - Form->Height) / 2) +
  655. ((TForm *)CenterForm)->Top;
  656. }
  657. else
  658. {
  659. X = (Screen->Width - Form->Width) / 2;
  660. Y = (Screen->Height - Form->Height) / 2;
  661. }
  662. if (X < 0)
  663. {
  664. X = 0;
  665. }
  666. if (Y < 0)
  667. {
  668. Y = 0;
  669. }
  670. Form->SetBounds(X, Y, Form->Width, Form->Height);
  671. }
  672. }
  673. //---------------------------------------------------------------------------
  674. void __fastcall ResizeForm(TForm * Form, int Width, int Height)
  675. {
  676. if (Height > Screen->WorkAreaHeight)
  677. {
  678. Height = Screen->WorkAreaHeight;
  679. }
  680. if (Width > Screen->WorkAreaWidth)
  681. {
  682. Width = Screen->WorkAreaWidth;
  683. }
  684. if (Height < Form->Constraints->MinHeight)
  685. {
  686. Height = Form->Constraints->MinHeight;
  687. }
  688. if (Width < Form->Constraints->MinWidth)
  689. {
  690. Width = Form->Constraints->MinWidth;
  691. }
  692. int Top = Form->Top + ((Form->Height - Height) / 2);
  693. int Left = Form->Left + ((Form->Width - Width) / 2);
  694. if (Top + Height > Screen->WorkAreaTop + Screen->WorkAreaHeight)
  695. {
  696. Top = Screen->WorkAreaTop + Screen->WorkAreaHeight - Height;
  697. }
  698. if (Left + Width >= Screen->WorkAreaLeft + Screen->WorkAreaWidth)
  699. {
  700. Left = Screen->WorkAreaLeft + Screen->WorkAreaWidth - Width;
  701. }
  702. if (Top < 0)
  703. {
  704. Top = 0;
  705. }
  706. if (Left < 0)
  707. {
  708. Left = 0;
  709. }
  710. Form->SetBounds(Left, Top, Width, Height);
  711. // due to constraints, form can remain larger, make sure it is centered although
  712. Left = Form->Left + ((Width - Form->Width) / 2);
  713. Top = Form->Top + ((Height - Form->Height) / 2);
  714. Form->SetBounds(Left, Top, Width, Height);
  715. }
  716. //---------------------------------------------------------------------------
  717. void __fastcall SetCorrectFormParent(TForm * Form)
  718. {
  719. try
  720. {
  721. // Kind of hack (i do not understand this much).
  722. // Rationale: for example when the preferences window is opened from login dialog
  723. // settings Parent to Screen->ActiveForm leads to "cannot focus disabled control",
  724. // so we set Parent only when absolutelly necessary
  725. // (dialog opened from log window or editor)
  726. // TODO: does not work for dialogs opened from preferences dialog
  727. if ((Application->MainForm != NULL) &&
  728. (Application->MainForm != Screen->ActiveForm))
  729. {
  730. // this should better be check for modal form
  731. AnsiString C = Screen->ActiveForm->Caption;
  732. if ((Screen->ActiveForm != NULL) &&
  733. (Screen->ActiveForm->BorderStyle != bsDialog))
  734. {
  735. Form->ParentWindow = Screen->ActiveForm->Handle;
  736. }
  737. }
  738. }
  739. catch(...)
  740. {
  741. // avoid any errors, however we want to know about this in debug version.
  742. #ifdef _DEBUG
  743. throw;
  744. #endif
  745. }
  746. }
  747. //---------------------------------------------------------------------------
  748. void __fastcall InvokeHelp(TWinControl * Control)
  749. {
  750. assert(Control != NULL);
  751. HELPINFO HelpInfo;
  752. HelpInfo.cbSize = sizeof(HelpInfo);
  753. HelpInfo.iContextType = HELPINFO_WINDOW;
  754. HelpInfo.iCtrlId = 0;
  755. HelpInfo.hItemHandle = Control->Handle;
  756. HelpInfo.dwContextId = 0;
  757. HelpInfo.MousePos.x = 0;
  758. HelpInfo.MousePos.y = 0;
  759. SendMessage(Control->Handle, WM_HELP, NULL, reinterpret_cast<long>(&HelpInfo));
  760. }
  761. //---------------------------------------------------------------------------
  762. //---------------------------------------------------------------------------
  763. static void __fastcall FocusableLabelCanvas(TStaticText * StaticText,
  764. TControlCanvas ** ACanvas, TRect & R)
  765. {
  766. TControlCanvas * Canvas = new TControlCanvas();
  767. try
  768. {
  769. Canvas->Control = StaticText;
  770. R = StaticText->ClientRect;
  771. AnsiString Caption = StaticText->Caption;
  772. bool AccelChar = false;
  773. if (StaticText->ShowAccelChar)
  774. {
  775. Caption = StripHotkey(Caption);
  776. AccelChar = (Caption != StaticText->Caption);
  777. }
  778. TSize TextSize = Canvas->TextExtent(Caption);
  779. assert(StaticText->BorderStyle == sbsNone); // not taken into account
  780. if (AccelChar)
  781. {
  782. TextSize.cy += 2;
  783. }
  784. R.Bottom = R.Top + TextSize.cy;
  785. if (StaticText->Alignment == taRightJustify)
  786. {
  787. R.Left = R.Right - TextSize.cx;
  788. }
  789. else
  790. {
  791. R.Right = R.Left + TextSize.cx;
  792. }
  793. }
  794. __finally
  795. {
  796. if (ACanvas == NULL)
  797. {
  798. delete Canvas;
  799. }
  800. }
  801. if (ACanvas != NULL)
  802. {
  803. *ACanvas = Canvas;
  804. }
  805. }
  806. //---------------------------------------------------------------------------
  807. static void __fastcall FocusableLabelWindowProc(void * Data, TMessage & Message,
  808. bool & Clicked)
  809. {
  810. Clicked = false;
  811. TStaticText * StaticText = static_cast<TStaticText *>(Data);
  812. if (Message.Msg == WM_LBUTTONDOWN)
  813. {
  814. StaticText->SetFocus();
  815. // in case the action takes long, make sure focus is shown immediatelly
  816. UpdateWindow(StaticText->Handle);
  817. Clicked = true;
  818. Message.Result = 1;
  819. }
  820. else if (Message.Msg == WM_RBUTTONDOWN)
  821. {
  822. StaticText->SetFocus();
  823. Message.Result = 1;
  824. }
  825. else if (Message.Msg == WM_CHAR)
  826. {
  827. if (reinterpret_cast<TWMChar &>(Message).CharCode == ' ')
  828. {
  829. Clicked = true;
  830. Message.Result = 1;
  831. }
  832. else
  833. {
  834. ControlWndProc(StaticText)(Message);
  835. }
  836. }
  837. else if (Message.Msg == CM_DIALOGCHAR)
  838. {
  839. if (StaticText->CanFocus() && StaticText->ShowAccelChar &&
  840. IsAccel(reinterpret_cast<TCMDialogChar &>(Message).CharCode, StaticText->Caption))
  841. {
  842. StaticText->SetFocus();
  843. // in case the action takes long, make sure focus is shown immediatelly
  844. UpdateWindow(StaticText->Handle);
  845. Clicked = true;
  846. Message.Result = 1;
  847. }
  848. else
  849. {
  850. ControlWndProc(StaticText)(Message);
  851. }
  852. }
  853. else
  854. {
  855. ControlWndProc(StaticText)(Message);
  856. }
  857. if (Message.Msg == WM_PAINT)
  858. {
  859. TRect R;
  860. TControlCanvas * Canvas;
  861. FocusableLabelCanvas(StaticText, &Canvas, R);
  862. try
  863. {
  864. if (StaticText->Focused())
  865. {
  866. Canvas->DrawFocusRect(R);
  867. }
  868. else if (!StaticText->Font->Style.Contains(fsUnderline))
  869. {
  870. Canvas->Pen->Style = psDot;
  871. Canvas->Brush->Style = bsClear;
  872. if (!StaticText->Enabled)
  873. {
  874. Canvas->Pen->Color = clBtnHighlight;
  875. Canvas->MoveTo(R.Left + 1 + 1, R.Bottom);
  876. Canvas->LineTo(R.Right + 1, R.Bottom);
  877. Canvas->Pen->Color = clGrayText;
  878. }
  879. Canvas->MoveTo(R.Left + 1, R.Bottom - 1);
  880. Canvas->LineTo(R.Right, R.Bottom - 1);
  881. }
  882. }
  883. __finally
  884. {
  885. delete Canvas;
  886. }
  887. }
  888. else if ((Message.Msg == WM_SETFOCUS) || (Message.Msg == WM_KILLFOCUS) ||
  889. (Message.Msg == CM_ENABLEDCHANGED))
  890. {
  891. StaticText->Invalidate();
  892. }
  893. }
  894. //---------------------------------------------------------------------------
  895. static THintWindow * PersistentHintWindow = NULL;
  896. static TControl * PersistentHintControl = NULL;
  897. //---------------------------------------------------------------------------
  898. void __fastcall CancelPersistentHint()
  899. {
  900. if (PersistentHintWindow != NULL)
  901. {
  902. PersistentHintControl = NULL;
  903. SAFE_DESTROY(PersistentHintWindow);
  904. }
  905. }
  906. //---------------------------------------------------------------------------
  907. void __fastcall ShowPersistentHint(TControl * Control, TPoint HintPos)
  908. {
  909. CancelPersistentHint();
  910. THintInfo HintInfo;
  911. HintInfo.HintControl = Control;
  912. HintInfo.HintPos = HintPos;
  913. HintInfo.HintMaxWidth = Screen->Width;
  914. HintInfo.HintColor = Application->HintColor;
  915. HintInfo.HintStr = GetShortHint(Control->Hint);
  916. HintInfo.HintData = NULL;
  917. bool CanShow = true;
  918. if (Application->OnShowHint != NULL)
  919. {
  920. Application->OnShowHint(HintInfo.HintStr, CanShow, HintInfo);
  921. }
  922. if (CanShow)
  923. {
  924. PersistentHintControl = Control;
  925. PersistentHintWindow = new THintWindow(Application);
  926. PersistentHintWindow->BiDiMode = Control->BiDiMode;
  927. PersistentHintWindow->Color = HintInfo.HintColor;
  928. TRect HintWinRect;
  929. if (HintInfo.HintMaxWidth < Control->Width)
  930. {
  931. HintInfo.HintMaxWidth = Control->Width;
  932. }
  933. HintWinRect = PersistentHintWindow->CalcHintRect(
  934. HintInfo.HintMaxWidth, HintInfo.HintStr, HintInfo.HintData);
  935. OffsetRect(HintWinRect, HintInfo.HintPos.x, HintInfo.HintPos.y);
  936. // TODO: right align window placement for UseRightToLeftAlignment, see Forms.pas
  937. PersistentHintWindow->ActivateHintData(HintWinRect, HintInfo.HintStr, HintInfo.HintData);
  938. }
  939. }
  940. //---------------------------------------------------------------------------
  941. static void __fastcall HintLabelWindowProc(void * Data, TMessage & Message)
  942. {
  943. bool Clicked = false;
  944. bool Cancel = false;
  945. TStaticText * StaticText = static_cast<TStaticText *>(Data);
  946. if (Message.Msg == CM_HINTSHOW)
  947. {
  948. TCMHintShow & HintShow = reinterpret_cast<TCMHintShow &>(Message);
  949. if (PersistentHintControl == StaticText)
  950. {
  951. // do not allow standard hint when persistent is already shown
  952. HintShow.Result = 1;
  953. }
  954. else
  955. {
  956. HintShow.HintInfo->HideTimeout = 100000; // never
  957. }
  958. }
  959. else if (Message.Msg == CN_KEYDOWN)
  960. {
  961. if ((reinterpret_cast<TWMKey &>(Message).CharCode == VK_ESCAPE) &&
  962. (PersistentHintControl == StaticText))
  963. {
  964. CancelPersistentHint();
  965. StaticText->Invalidate();
  966. Message.Result = 1;
  967. }
  968. else
  969. {
  970. FocusableLabelWindowProc(Data, Message, Clicked);
  971. }
  972. }
  973. else
  974. {
  975. FocusableLabelWindowProc(Data, Message, Clicked);
  976. }
  977. if (Message.Msg == CM_CANCELMODE)
  978. {
  979. TCMCancelMode & CancelMessage = (TCMCancelMode&)Message;
  980. if ((CancelMessage.Sender != StaticText) &&
  981. (CancelMessage.Sender != PersistentHintWindow))
  982. {
  983. Cancel = true;
  984. }
  985. }
  986. if ((Message.Msg == WM_DESTROY) || (Message.Msg == WM_KILLFOCUS))
  987. {
  988. Cancel = true;
  989. }
  990. if (Cancel && (PersistentHintControl == StaticText))
  991. {
  992. CancelPersistentHint();
  993. }
  994. if (Clicked && (PersistentHintControl != StaticText))
  995. {
  996. TRect R;
  997. TPoint HintPos;
  998. FocusableLabelCanvas(StaticText, NULL, R);
  999. HintPos.y = R.Bottom - R.Top;
  1000. HintPos.x = R.Left;
  1001. ShowPersistentHint(StaticText, StaticText->ClientToScreen(HintPos));
  1002. }
  1003. }
  1004. //---------------------------------------------------------------------------
  1005. void __fastcall HintLabel(TStaticText * StaticText, AnsiString Hint)
  1006. {
  1007. StaticText->ParentFont = true;
  1008. if (!Hint.IsEmpty())
  1009. {
  1010. StaticText->Hint = Hint;
  1011. }
  1012. StaticText->ShowHint = true;
  1013. StaticText->Cursor = crHandPoint;
  1014. TWndMethod WindowProc;
  1015. ((TMethod*)&WindowProc)->Data = StaticText;
  1016. ((TMethod*)&WindowProc)->Code = HintLabelWindowProc;
  1017. StaticText->WindowProc = WindowProc;
  1018. }
  1019. //---------------------------------------------------------------------------
  1020. void __fastcall HintLabelRestore(TStaticText * StaticText)
  1021. {
  1022. StaticText->WindowProc = ControlWndProc(StaticText);
  1023. StaticText->ShowHint = false;
  1024. StaticText->Cursor = crDefault;
  1025. }
  1026. //---------------------------------------------------------------------------
  1027. static void __fastcall LinkLabelClick(TStaticText * StaticText)
  1028. {
  1029. if (StaticText->OnClick != NULL)
  1030. {
  1031. StaticText->OnClick(StaticText);
  1032. }
  1033. else
  1034. {
  1035. AnsiString Url = StaticText->Caption;
  1036. if (!SameText(Url.SubString(1, 4), "http") && (Url.Pos("@") > 0))
  1037. {
  1038. Url = "mailto:" + Url;
  1039. }
  1040. OpenBrowser(Url);
  1041. }
  1042. }
  1043. //---------------------------------------------------------------------------
  1044. static void __fastcall LinkLabelWindowProc(void * Data, TMessage & Message)
  1045. {
  1046. bool Clicked = false;
  1047. TStaticText * StaticText = static_cast<TStaticText *>(Data);
  1048. if (Message.Msg == WM_CONTEXTMENU)
  1049. {
  1050. TWMContextMenu & ContextMenu = reinterpret_cast<TWMContextMenu &>(Message);
  1051. if ((ContextMenu.Pos.x < 0) && (ContextMenu.Pos.y < 0))
  1052. {
  1053. TRect R;
  1054. FocusableLabelCanvas(StaticText, NULL, R);
  1055. TPoint P = StaticText->ClientToScreen(TPoint(R.Left, R.Bottom));
  1056. ContextMenu.Pos.x = static_cast<short>(P.x);
  1057. ContextMenu.Pos.y = static_cast<short>(P.y);
  1058. }
  1059. }
  1060. else if (Message.Msg == WM_KEYDOWN)
  1061. {
  1062. TWMKey & Key = reinterpret_cast<TWMKey &>(Message);
  1063. if ((GetKeyState(VK_CONTROL) < 0) && (Key.CharCode == 'C'))
  1064. {
  1065. CopyToClipboard(StaticText->Caption);
  1066. Message.Result = 1;
  1067. }
  1068. else
  1069. {
  1070. FocusableLabelWindowProc(Data, Message, Clicked);
  1071. }
  1072. }
  1073. FocusableLabelWindowProc(Data, Message, Clicked);
  1074. if (Message.Msg == WM_DESTROY)
  1075. {
  1076. delete StaticText->PopupMenu;
  1077. assert(StaticText->PopupMenu == NULL);
  1078. }
  1079. if (Clicked)
  1080. {
  1081. LinkLabelClick(StaticText);
  1082. }
  1083. }
  1084. //---------------------------------------------------------------------------
  1085. static void __fastcall LinkLabelContextMenuClick(void * Data, TObject * Sender)
  1086. {
  1087. TStaticText * StaticText = static_cast<TStaticText *>(Data);
  1088. TMenuItem * MenuItem = dynamic_cast<TMenuItem *>(Sender);
  1089. assert(MenuItem != NULL);
  1090. if (MenuItem->Tag == 0)
  1091. {
  1092. LinkLabelClick(StaticText);
  1093. }
  1094. else
  1095. {
  1096. CopyToClipboard(StaticText->Caption);
  1097. }
  1098. }
  1099. //---------------------------------------------------------------------------
  1100. void __fastcall LinkLabel(TStaticText * StaticText, AnsiString Url,
  1101. TNotifyEvent OnEnter)
  1102. {
  1103. StaticText->ParentFont = true;
  1104. StaticText->Font->Style = StaticText->Font->Style << fsUnderline;
  1105. StaticText->Font->Color = clBlue;
  1106. StaticText->Cursor = crHandPoint;
  1107. reinterpret_cast<TButton*>(StaticText)->OnEnter = OnEnter;
  1108. if (!Url.IsEmpty())
  1109. {
  1110. StaticText->Caption = Url;
  1111. }
  1112. if (StaticText->OnClick == NULL)
  1113. {
  1114. assert(StaticText->PopupMenu == NULL);
  1115. StaticText->PopupMenu = new TPopupMenu(StaticText);
  1116. try
  1117. {
  1118. TNotifyEvent ContextMenuOnClick;
  1119. ((TMethod*)&ContextMenuOnClick)->Data = StaticText;
  1120. ((TMethod*)&ContextMenuOnClick)->Code = LinkLabelContextMenuClick;
  1121. TMenuItem * Item;
  1122. Item = new TMenuItem(StaticText->PopupMenu);
  1123. Item->Caption = LoadStr(URL_LINK_OPEN);
  1124. Item->Tag = 0;
  1125. Item->ShortCut = ShortCut(' ', TShiftState());
  1126. Item->OnClick = ContextMenuOnClick;
  1127. StaticText->PopupMenu->Items->Add(Item);
  1128. Item = new TMenuItem(StaticText->PopupMenu);
  1129. Item->Caption = LoadStr(URL_LINK_COPY);
  1130. Item->Tag = 1;
  1131. Item->ShortCut = ShortCut('C', TShiftState() << ssCtrl);
  1132. Item->OnClick = ContextMenuOnClick;
  1133. StaticText->PopupMenu->Items->Add(Item);
  1134. }
  1135. catch(...)
  1136. {
  1137. delete StaticText->PopupMenu;
  1138. assert(StaticText->PopupMenu == NULL);
  1139. throw;
  1140. }
  1141. }
  1142. TWndMethod WindowProc;
  1143. ((TMethod*)&WindowProc)->Data = StaticText;
  1144. ((TMethod*)&WindowProc)->Code = LinkLabelWindowProc;
  1145. StaticText->WindowProc = WindowProc;
  1146. }
  1147. //---------------------------------------------------------------------------
  1148. int __fastcall SafeShowModal(TForm * Form)
  1149. {
  1150. // FIX: Due to some bug in Theme Manager, certain forms randomly
  1151. // fails in call to ShowModal(), hence repeat the call until it succeeds.
  1152. int Result = -1;
  1153. int Retry = 0;
  1154. do
  1155. {
  1156. try
  1157. {
  1158. Result = Form->ShowModal();
  1159. }
  1160. catch (EOSError & E)
  1161. {
  1162. if (E.Message == Sysconst_SUnkOSError)
  1163. {
  1164. ++Retry;
  1165. if (Retry >= 10)
  1166. {
  1167. throw;
  1168. }
  1169. else
  1170. {
  1171. Form->Visible = false;
  1172. }
  1173. }
  1174. else
  1175. {
  1176. throw;
  1177. }
  1178. }
  1179. }
  1180. while (Result < 0);
  1181. return Result;
  1182. }
  1183. //---------------------------------------------------------------------------
  1184. static void __fastcall CreateHandles(TWinControl * Control)
  1185. {
  1186. Control->HandleNeeded();
  1187. for (int Index = 0; Index < Control->ControlCount; Index++)
  1188. {
  1189. TWinControl * ChildControl = dynamic_cast<TWinControl *>(Control->Controls[Index]);
  1190. if (ChildControl != NULL)
  1191. {
  1192. CreateHandles(ChildControl);
  1193. }
  1194. }
  1195. }
  1196. //---------------------------------------------------------------------------
  1197. TForm * __fastcall _SafeFormValidate(TForm * Form, int & Retry)
  1198. {
  1199. try
  1200. {
  1201. CreateHandles(Form);
  1202. }
  1203. catch (EOSError & E)
  1204. {
  1205. delete Form;
  1206. Form = NULL;
  1207. ++Retry;
  1208. if ((E.Message != Sysconst_SUnkOSError) ||
  1209. (Retry >= 10))
  1210. {
  1211. throw;
  1212. }
  1213. }
  1214. catch(...)
  1215. {
  1216. delete Form;
  1217. }
  1218. return Form;
  1219. }