WinInterface.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include <MoreButton.hpp>
  5. #include <Common.h>
  6. #include <Net.h>
  7. #include <SecureShell.h>
  8. #include <ScpMain.h>
  9. #include <TextsWin.h>
  10. #include <Interface.h>
  11. #include "WinInterface.h"
  12. #include "WinConfiguration.h"
  13. #include "TerminalManager.h"
  14. #define mrCustom (mrYesToAll + 1)
  15. //---------------------------------------------------------------------------
  16. #pragma package(smart_init)
  17. //---------------------------------------------------------------------------
  18. TConfiguration * __fastcall CreateConfiguration()
  19. {
  20. return new TWinConfiguration();
  21. }
  22. //---------------------------------------------------------------------------
  23. void __fastcall FlashOnBackground()
  24. {
  25. assert(Application);
  26. if (GetForegroundWindow() != GetActiveWindow())
  27. {
  28. FlashWindow(Application->Handle, true);
  29. }
  30. }
  31. //---------------------------------------------------------------------------
  32. void __fastcall ShowExtendedException(Exception * E, TObject * Sender)
  33. {
  34. if (!E->Message.IsEmpty())
  35. {
  36. if (E->InheritsFrom(__classid(Exception)))
  37. {
  38. if (!E->InheritsFrom(__classid(EAbort)))
  39. {
  40. TQueryType Type;
  41. Type = (E->InheritsFrom(__classid(ESshTerminate)) ?
  42. qtInformation : qtError);
  43. if (E->InheritsFrom(__classid(EFatal)))
  44. {
  45. if (FatalExceptionMessageDialog(E, Type) == qaRetry)
  46. {
  47. TTerminalManager::Instance()->ReconnectActiveTerminal();
  48. }
  49. else
  50. {
  51. TTerminalManager::Instance()->FreeActiveTerminal();
  52. }
  53. }
  54. else
  55. {
  56. ExceptionMessageDialog(E, Type, qaOK);
  57. }
  58. }
  59. }
  60. else
  61. {
  62. FlashOnBackground();
  63. ShowException(ExceptObject(), ExceptAddr());
  64. }
  65. }
  66. HandleExtendedException(E, Sender);
  67. }
  68. //---------------------------------------------------------------------------
  69. void __fastcall HandleExtendedException(Exception * E, TObject* /*Sender*/)
  70. {
  71. if (TTerminalManager::Instance()->ActiveTerminal)
  72. {
  73. TTerminalManager::Instance()->ActiveTerminal->Log->AddException(E);
  74. }
  75. /*if (E->InheritsFrom(__classid(EFatal)))
  76. {
  77. Application->Terminate();
  78. }*/
  79. }
  80. //---------------------------------------------------------------------------
  81. TForm * CreateMessageDialogEx(const AnsiString Msg, TQueryType Type,
  82. int Answers, int HelpCtx, int Params)
  83. {
  84. TMsgDlgButtons Buttons;
  85. TMsgDlgType DlgType;
  86. switch (Type) {
  87. case qtConfirmation: DlgType = mtConfirmation; break;
  88. case qtInformation: DlgType = mtInformation; break;
  89. case qtError: DlgType = mtError; break;
  90. case qtWarning: DlgType = mtWarning; break;
  91. default: assert(false);
  92. }
  93. #define ADD_BUTTON(TYPE) if (Answers & qa ## TYPE) Buttons << mb ## TYPE;
  94. ADD_BUTTON(Yes);
  95. ADD_BUTTON(No);
  96. ADD_BUTTON(OK);
  97. ADD_BUTTON(Cancel);
  98. ADD_BUTTON(Abort);
  99. ADD_BUTTON(Retry);
  100. ADD_BUTTON(Ignore);
  101. ADD_BUTTON(All);
  102. ADD_BUTTON(NoToAll);
  103. ADD_BUTTON(YesToAll);
  104. ADD_BUTTON(Help);
  105. #undef ADD_BUTTON
  106. if (Answers & qaSkip)
  107. {
  108. assert((Answers & qaIgnore) == 0);
  109. Buttons << mbIgnore;
  110. }
  111. if (Answers & qaPrev)
  112. {
  113. assert((Answers & qaYes) == 0);
  114. Buttons << mbYes;
  115. }
  116. if (Answers & qaNext)
  117. {
  118. assert((Answers & qaNo) == 0);
  119. Buttons << mbNo;
  120. }
  121. if (Answers & qaCustom)
  122. {
  123. assert((Answers & qaHelp) == 0);
  124. Buttons << mbHelp;
  125. }
  126. assert(!Buttons.Empty());
  127. TForm * Dialog = CreateMessageDialog(Msg, DlgType, Buttons);
  128. try
  129. {
  130. if (Answers & qaSkip)
  131. {
  132. TButton * IgnoreButton = dynamic_cast<TButton *>(Dialog->FindComponent("Ignore"));
  133. assert(IgnoreButton);
  134. IgnoreButton->Caption = LoadStr(SKIP_BUTTON);
  135. }
  136. if (Answers & qaPrev)
  137. {
  138. TButton * YesButton = dynamic_cast<TButton *>(Dialog->FindComponent("Yes"));
  139. assert(YesButton);
  140. YesButton->Caption = LoadStr(PREV_BUTTON);
  141. }
  142. if (Answers & qaNext)
  143. {
  144. TButton * NoButton = dynamic_cast<TButton *>(Dialog->FindComponent("No"));
  145. assert(NoButton);
  146. NoButton->Caption = LoadStr(NEXT_BUTTON);
  147. }
  148. if (Answers & qaCustom)
  149. {
  150. TButton * HelpButton = dynamic_cast<TButton *>(Dialog->FindComponent("Help"));
  151. assert(HelpButton);
  152. HelpButton->Name = "Custom";
  153. HelpButton->ModalResult = mrCustom;
  154. }
  155. // temporary fix of accelerators (&Abort vs. &All/Yes to &All)
  156. // must be removed
  157. for (int Index = 0; Index < Dialog->ComponentCount; Index++)
  158. {
  159. TButton * B = dynamic_cast<TButton *>(Dialog->Components[Index]);
  160. if (B)
  161. {
  162. if (B->Caption == "&All") B->Caption = "A&ll";
  163. else
  164. if (B->Caption == "Yes to &All") B->Caption = "Yes to A&ll";
  165. }
  166. }
  167. if (Params & mpNeverAskAgainCheck)
  168. {
  169. Dialog->ClientHeight = Dialog->ClientHeight + 20;
  170. TCheckBox * NeverAskAgainCheck = new TCheckBox(Dialog);
  171. NeverAskAgainCheck->Name = "NeverAskAgainCheck";
  172. NeverAskAgainCheck->Parent = Dialog;
  173. NeverAskAgainCheck->BoundsRect = TRect(60, Dialog->ClientHeight - 27,
  174. Dialog->ClientWidth - 10, Dialog->ClientHeight - 5);
  175. NeverAskAgainCheck->Caption = LoadStr(NEVER_ASK_AGAIN);
  176. NeverAskAgainCheck->Checked = false;
  177. }
  178. Dialog->HelpContext = HelpCtx;
  179. Dialog->Position = poMainFormCenter;
  180. }
  181. catch(...)
  182. {
  183. delete Dialog;
  184. throw;
  185. }
  186. return Dialog;
  187. }
  188. //---------------------------------------------------------------------------
  189. int ExecuteMessageDialog(TForm * Dialog, int Answers, int Params)
  190. {
  191. int Result, Answer;
  192. FlashOnBackground();
  193. Result = Dialog->ShowModal();
  194. switch (Result) {
  195. #define MAP_RESULT(RESULT) case mr ## RESULT: Answer = qa ## RESULT; break;
  196. MAP_RESULT(Cancel);
  197. MAP_RESULT(Abort);
  198. MAP_RESULT(Retry);
  199. MAP_RESULT(All);
  200. MAP_RESULT(NoToAll);
  201. MAP_RESULT(YesToAll);
  202. MAP_RESULT(Custom);
  203. #undef MAP_RESULT
  204. case mrOk:
  205. Answer = qaOK;
  206. break;
  207. case mrIgnore:
  208. Answer = (Answers & qaSkip) ? qaSkip : qaIgnore;
  209. break;
  210. case mrYes:
  211. Answer = (Answers & qaPrev) ? qaPrev : qaYes;
  212. break;
  213. case mrNo:
  214. Answer = (Answers & qaNext) ? qaNext : qaNo;
  215. break;
  216. }
  217. if (Params & mpNeverAskAgainCheck)
  218. {
  219. TCheckBox * NeverAskAgainCheck =
  220. dynamic_cast<TCheckBox *>(Dialog->FindComponent("NeverAskAgainCheck"));
  221. assert(NeverAskAgainCheck);
  222. if (NeverAskAgainCheck->Checked &&
  223. (Answer == qaYes || Answer == qaOK || Answer == qaYesToAll))
  224. {
  225. Answer = qaNeverAskAgain;
  226. }
  227. }
  228. TMoreButton * MoreButton = dynamic_cast<TMoreButton *>(Dialog->FindComponent("MoreButton"));
  229. if (MoreButton)
  230. {
  231. // store state even when user selects 'Cancel'?
  232. WinConfiguration->ErrorDialogExpanded = MoreButton->Expanded;
  233. }
  234. return Answer;
  235. }
  236. //---------------------------------------------------------------------------
  237. int __fastcall MessageDialog(const AnsiString Msg, TQueryType Type,
  238. int Answers, int HelpCtx, int Params)
  239. {
  240. int Result;
  241. TForm * Dialog = CreateMessageDialogEx(Msg, Type, Answers, HelpCtx, Params);
  242. try
  243. {
  244. Result = ExecuteMessageDialog(Dialog, Answers, Params);
  245. }
  246. __finally
  247. {
  248. delete Dialog;
  249. }
  250. return Result;
  251. }
  252. //---------------------------------------------------------------------------
  253. TForm * __fastcall CreateMoreMessageDialog(const AnsiString Message,
  254. TStrings * MoreMessages, TQueryType Type, int Answers,
  255. int HelpCtx, int Params)
  256. {
  257. if (!MoreMessages || (MoreMessages->Count == 0))
  258. {
  259. return CreateMessageDialogEx(Message, Type, Answers, HelpCtx, Params);
  260. }
  261. else
  262. {
  263. TForm * Dialog;
  264. Answers |= qaCustom;
  265. Dialog = CreateMessageDialogEx(Message, Type, Answers, HelpCtx, Params);
  266. try
  267. {
  268. TButton * CustomButton = dynamic_cast<TButton *>(Dialog->FindComponent("Custom"));
  269. TLabel * MsgLabel = dynamic_cast<TLabel *>(Dialog->FindComponent("Message"));
  270. assert(MsgLabel && CustomButton);
  271. int OrigButtonTop = CustomButton->Top;
  272. int WidthDelta = 0;
  273. if (Dialog->ClientWidth < 400)
  274. {
  275. WidthDelta = (400 - Dialog->ClientWidth);
  276. }
  277. Dialog->ClientHeight = Dialog->ClientHeight + 130;
  278. Dialog->ClientWidth = Dialog->ClientWidth + WidthDelta;
  279. MsgLabel->Width = MsgLabel->Width + WidthDelta;
  280. for (int Index = 0; Index < Dialog->ControlCount; Index++)
  281. {
  282. if (Dialog->Controls[Index]->InheritsFrom(__classid(TButton)))
  283. {
  284. TControl * Control = Dialog->Controls[Index];
  285. Control->Anchors = TAnchors() << akBottom << akLeft;
  286. Control->Top = Control->Top + 130;
  287. Control->Left = Control->Left + (WidthDelta / 2);
  288. }
  289. }
  290. TMemo * MessageMemo = new TMemo(Dialog);
  291. MessageMemo->Parent = Dialog;
  292. MessageMemo->ReadOnly = True;
  293. MessageMemo->WantReturns = False;
  294. MessageMemo->ScrollBars = ssVertical;
  295. MessageMemo->Anchors = TAnchors() << akLeft << akRight << akTop; //akBottom;
  296. MessageMemo->BoundsRect = TRect(MsgLabel->Left, OrigButtonTop - 10,
  297. Dialog->ClientWidth - 20, CustomButton->Top - 10);
  298. MessageMemo->Color = clBtnFace;
  299. MessageMemo->Lines->Text = MoreMessages->Text;
  300. TMoreButton * MoreButton = new TMoreButton(Dialog);
  301. MoreButton->Parent = Dialog;
  302. MoreButton->BoundsRect = CustomButton->BoundsRect;
  303. MoreButton->Anchors = CustomButton->Anchors;
  304. MoreButton->Panel = MessageMemo;
  305. MoreButton->Expanded = WinConfiguration->ErrorDialogExpanded;
  306. MoreButton->Name = "MoreButton";
  307. MessageMemo->TabOrder = 20;
  308. delete CustomButton;
  309. }
  310. catch(...)
  311. {
  312. delete Dialog;
  313. throw;
  314. }
  315. return Dialog;
  316. }
  317. }
  318. //---------------------------------------------------------------------------
  319. int __fastcall MoreMessageDialog(const AnsiString Message, TStrings * MoreMessages,
  320. TQueryType Type, int Answers, int HelpCtx, int Params)
  321. {
  322. int Result;
  323. TForm * Dialog;
  324. Dialog = CreateMoreMessageDialog(Message, MoreMessages, Type,
  325. Answers, HelpCtx, Params);
  326. try
  327. {
  328. Result = ExecuteMessageDialog(Dialog, Answers, Params);
  329. }
  330. __finally
  331. {
  332. delete Dialog;
  333. }
  334. return Result;
  335. }
  336. //---------------------------------------------------------------------------
  337. int __fastcall SimpleErrorDialog(const AnsiString Msg)
  338. {
  339. return MessageDialog(Msg, qtError, qaOK, 0);
  340. }
  341. //---------------------------------------------------------------------------
  342. int __fastcall ExceptionMessageDialog(Exception * E,
  343. TQueryType Type, int Answers, int HelpCtx)
  344. {
  345. TStrings * MoreMessages = NULL;
  346. if (E->InheritsFrom(__classid(ExtException)))
  347. {
  348. MoreMessages = ((ExtException *)E)->MoreMessages;
  349. }
  350. int Result;
  351. TForm * Dialog;
  352. Dialog = CreateMoreMessageDialog(E->Message, MoreMessages, Type,
  353. Answers, HelpCtx, 0);
  354. try
  355. {
  356. Result = ExecuteMessageDialog(Dialog, Answers, 0);
  357. }
  358. __finally
  359. {
  360. delete Dialog;
  361. }
  362. return Result;
  363. }
  364. //---------------------------------------------------------------------------
  365. int __fastcall FatalExceptionMessageDialog(Exception * E,
  366. TQueryType Type, int HelpCtx)
  367. {
  368. TStrings * MoreMessages = NULL;
  369. if (E->InheritsFrom(__classid(ExtException)))
  370. {
  371. MoreMessages = ((ExtException *)E)->MoreMessages;
  372. }
  373. int Result, Answers;
  374. Answers = qaOK | qaRetry;
  375. TForm * Dialog = CreateMoreMessageDialog(E->Message, MoreMessages, Type,
  376. Answers, HelpCtx, 0);
  377. try
  378. {
  379. TButton * RetryButton = dynamic_cast<TButton *>(Dialog->FindComponent("Retry"));
  380. assert(RetryButton);
  381. RetryButton->Caption = LoadStr(RECONNECT_BUTTON);
  382. Result = ExecuteMessageDialog(Dialog, Answers, 0);
  383. }
  384. __finally
  385. {
  386. delete Dialog;
  387. }
  388. return Result;
  389. }
  390. //---------------------------------------------------------------------------
  391. int __fastcall GetSessionPassword(AnsiString Prompt, AnsiString & Password)
  392. {
  393. return DoPasswordDialog(Prompt, Password);
  394. }
  395. //---------------------------------------------------------------------------
  396. void __fastcall Busy(bool Start)
  397. {
  398. static int Busy = 0;
  399. static TCursor PrevCursor;
  400. if (Start)
  401. {
  402. if (!Busy)
  403. {
  404. PrevCursor = Screen->Cursor;
  405. Screen->Cursor = crHourGlass;
  406. }
  407. Busy++;
  408. assert(Busy < 10);
  409. }
  410. else
  411. {
  412. assert(Busy > 0);
  413. Busy--;
  414. if (!Busy)
  415. {
  416. Screen->Cursor = PrevCursor;
  417. }
  418. }
  419. }
  420. //---------------------------------------------------------------------------
  421. AnsiString __fastcall SshVersionString()
  422. {
  423. return FORMAT("WinSCP-release-%s", (Configuration->Version));
  424. }