MessageDlg.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include <Consts.hpp>
  5. #include <MoreButton.hpp>
  6. #include <GUITools.h>
  7. #include <Common.h>
  8. #include <VCLCommon.h>
  9. #include <WinInterface.h>
  10. //---------------------------------------------------------------------------
  11. #pragma package(smart_init)
  12. //---------------------------------------------------------------------------
  13. class TMessageForm : public TForm
  14. {
  15. public:
  16. static TForm * __fastcall Create(const AnsiString & Msg, TStrings * MoreMessages,
  17. TMsgDlgType DlgType, TMsgDlgButtons Buttons,
  18. TQueryButtonAlias * Aliases, unsigned int AliasesCount);
  19. protected:
  20. __fastcall TMessageForm(TComponent * AOwner);
  21. DYNAMIC void __fastcall KeyDown(Word & Key, TShiftState Shift);
  22. AnsiString __fastcall GetFormText();
  23. private:
  24. TLabel * Message;
  25. TMemo * MessageMemo;
  26. void __fastcall HelpButtonClick(TObject * Sender);
  27. };
  28. //---------------------------------------------------------------------------
  29. __fastcall TMessageForm::TMessageForm(TComponent * AOwner) : TForm(AOwner, 0)
  30. {
  31. Message = NULL;
  32. MessageMemo = NULL;
  33. TNonClientMetrics NonClientMetrics;
  34. NonClientMetrics.cbSize = sizeof(NonClientMetrics);
  35. if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &NonClientMetrics, 0))
  36. {
  37. Font->Handle = CreateFontIndirect(&NonClientMetrics.lfMessageFont);
  38. }
  39. }
  40. //---------------------------------------------------------------------------
  41. void __fastcall TMessageForm::HelpButtonClick(TObject * /*Sender*/)
  42. {
  43. Application->HelpContext(HelpContext);
  44. }
  45. //---------------------------------------------------------------------------
  46. void __fastcall TMessageForm::KeyDown(Word & Key, TShiftState Shift)
  47. {
  48. if (Shift.Contains(ssCtrl) && (Key == 'C'))
  49. {
  50. CopyToClipboard(GetFormText());
  51. }
  52. }
  53. //---------------------------------------------------------------------------
  54. AnsiString __fastcall TMessageForm::GetFormText()
  55. {
  56. AnsiString DividerLine, ButtonCaptions;
  57. DividerLine = AnsiString::StringOfChar('-', 27) + sLineBreak;
  58. for (int i = 0; i < ComponentCount - 1; i++)
  59. {
  60. if ((dynamic_cast<TButton*>(Components[i]) != NULL) &&
  61. (dynamic_cast<TMoreButton*>(Components[i]) == NULL))
  62. {
  63. ButtonCaptions += dynamic_cast<TButton*>(Components[i])->Caption +
  64. AnsiString::StringOfChar(' ', 3);
  65. }
  66. }
  67. ButtonCaptions = StringReplace(ButtonCaptions, "&", "",
  68. TReplaceFlags() << rfReplaceAll);
  69. AnsiString MoreMessages;
  70. if (MessageMemo != NULL)
  71. {
  72. MoreMessages = MessageMemo->Text + DividerLine;
  73. }
  74. AnsiString Result = FORMAT("%s%s%s%s%s%s%s%s%s%s%s", (DividerLine, Caption, sLineBreak,
  75. DividerLine, Message->Caption, sLineBreak, DividerLine, MoreMessages,
  76. ButtonCaptions, sLineBreak, DividerLine));
  77. return Result;
  78. }
  79. //---------------------------------------------------------------------------
  80. const ResourceString * Captions[] = { &_SMsgDlgWarning, &_SMsgDlgError, &_SMsgDlgInformation,
  81. &_SMsgDlgConfirm, NULL };
  82. const char * IconIDs[] = { IDI_EXCLAMATION, IDI_HAND, IDI_ASTERISK,
  83. IDI_QUESTION, NULL };
  84. const int ButtonCount = 11;
  85. const AnsiString ButtonNames[ButtonCount] = {
  86. "Yes", "No", "OK", "Cancel", "Abort", "Retry", "Ignore", "All", "NoToAll",
  87. "YesToAll", "Help" };
  88. const ResourceString * ButtonCaptions[ButtonCount] = {
  89. &_SMsgDlgYes, &_SMsgDlgNo, &_SMsgDlgOK, &_SMsgDlgCancel, &_SMsgDlgAbort,
  90. &_SMsgDlgRetry, &_SMsgDlgIgnore, &_SMsgDlgAll, &_SMsgDlgNoToAll, &_SMsgDlgYesToAll,
  91. &_SMsgDlgHelp };
  92. const int ModalResults[ButtonCount] = {
  93. mrYes, mrNo, mrOk, mrCancel, mrAbort, mrRetry, mrIgnore, mrAll, mrNoToAll,
  94. mrYesToAll, 0 };
  95. const int mcHorzMargin = 8;
  96. const int mcVertMargin = 8;
  97. const int mcHorzSpacing = 10;
  98. const int mcVertSpacing = 10;
  99. const int mcButtonWidth = 50;
  100. const int mcButtonHeight = 14;
  101. const int mcButtonSpacing = 4;
  102. const int mcMoreMessageWidth = 320;
  103. const int mcMoreMessageHeight = 80;
  104. //---------------------------------------------------------------------------
  105. TForm * __fastcall TMessageForm::Create(const AnsiString & Msg,
  106. TStrings * MoreMessages, TMsgDlgType DlgType, TMsgDlgButtons Buttons,
  107. TQueryButtonAlias * Aliases, unsigned int AliasesCount)
  108. {
  109. TRect TextRect;
  110. TMsgDlgBtn DefaultButton, CancelButton;
  111. if (Buttons.Contains(mbOK))
  112. {
  113. DefaultButton = mbOK;
  114. }
  115. else if (Buttons.Contains(mbYes))
  116. {
  117. DefaultButton = mbYes;
  118. }
  119. else
  120. {
  121. DefaultButton = mbRetry;
  122. }
  123. if (Buttons.Contains(mbCancel))
  124. {
  125. CancelButton = mbCancel;
  126. }
  127. else if (Buttons.Contains(mbNo))
  128. {
  129. CancelButton = mbNo;
  130. }
  131. else if (Buttons.Contains(mbAbort))
  132. {
  133. CancelButton = mbAbort;
  134. }
  135. else
  136. {
  137. CancelButton = mbOK;
  138. }
  139. TMessageForm * Result = new TMessageForm(Application);
  140. Result->BiDiMode = Application->BiDiMode;
  141. Result->BorderStyle = bsDialog;
  142. Result->Canvas->Font = Result->Font;
  143. Result->KeyPreview = true;
  144. TPoint DialogUnits = GetAveCharSize(Result->Canvas);
  145. int HorzMargin = MulDiv(mcHorzMargin, DialogUnits.x, 4);
  146. int VertMargin = MulDiv(mcVertMargin, DialogUnits.y, 8);
  147. int HorzSpacing = MulDiv(mcHorzSpacing, DialogUnits.x, 4);
  148. int VertSpacing = MulDiv(mcVertSpacing, DialogUnits.y, 8);
  149. int ButtonWidth = MulDiv(mcButtonWidth, DialogUnits.x, 4);
  150. TButton * ButtonControls[ButtonCount + 1];
  151. int ButtonControlsCount = 0;
  152. for (unsigned int B = mbYes; B <= mbHelp; B++)
  153. {
  154. assert(B < ButtonCount);
  155. if (Buttons.Contains(TMsgDlgBtn(B)))
  156. {
  157. TextRect = Rect(0,0,0,0);
  158. AnsiString Caption = LoadResourceString(ButtonCaptions[B]);
  159. // temporary fix of accelerators (&Abort vs. &All/Yes to &All)
  160. // must be removed
  161. if (Caption == "&All")
  162. {
  163. Caption = "A&ll";
  164. }
  165. else if (Caption == "Yes to &All")
  166. {
  167. Caption = "Yes to A&ll";
  168. }
  169. if (Aliases != NULL)
  170. {
  171. for (unsigned int i = 0; i < AliasesCount; i++)
  172. {
  173. if (B == Aliases[i].Button)
  174. {
  175. Caption = Aliases[i].Alias;
  176. break;
  177. }
  178. }
  179. }
  180. DrawText(Result->Canvas->Handle,
  181. Caption.c_str(), -1,
  182. &TextRect, DT_CALCRECT | DT_LEFT | DT_SINGLELINE |
  183. Result->DrawTextBiDiModeFlagsReadingOnly());
  184. int CurButtonWidth = TextRect.Right - TextRect.Left + 8;
  185. if (CurButtonWidth > ButtonWidth)
  186. {
  187. ButtonWidth = CurButtonWidth;
  188. }
  189. TButton * Button = new TButton(Result);
  190. Button->Name = ButtonNames[TMsgDlgBtn(B)];
  191. Button->Parent = Result;
  192. Button->Caption = Caption;
  193. Button->ModalResult = ModalResults[B];
  194. Button->Default = (B == DefaultButton);
  195. Button->Cancel = (B == CancelButton);
  196. if (MoreMessages != NULL)
  197. {
  198. Button->Anchors = TAnchors() << akBottom << akLeft;
  199. }
  200. if (B == mbHelp)
  201. {
  202. Button->OnClick = Result->HelpButtonClick;
  203. }
  204. ButtonControls[ButtonControlsCount] = Button;
  205. ButtonControlsCount++;
  206. }
  207. }
  208. int ButtonHeight = MulDiv(mcButtonHeight, DialogUnits.y, 8);
  209. int ButtonSpacing = MulDiv(mcButtonSpacing, DialogUnits.x, 4);
  210. SetRect(&TextRect, 0, 0, Screen->Width / 2, 0);
  211. DrawText(Result->Canvas->Handle, Msg.c_str(), Msg.Length() + 1, &TextRect,
  212. DT_EXPANDTABS | DT_CALCRECT | DT_WORDBREAK |
  213. Result->DrawTextBiDiModeFlagsReadingOnly());
  214. const char * IconID = IconIDs[DlgType];
  215. int IconTextWidth = TextRect.Right;
  216. int IconTextHeight = TextRect.Bottom;
  217. if (IconID != NULL)
  218. {
  219. IconTextWidth += 32 + HorzSpacing;
  220. if (IconTextHeight < 32)
  221. {
  222. IconTextHeight = 32;
  223. }
  224. }
  225. if (MoreMessages != NULL)
  226. {
  227. TMemo * MessageMemo = new TMemo(Result);
  228. MessageMemo->Parent = Result;
  229. MessageMemo->ReadOnly = true;
  230. MessageMemo->WantReturns = False;
  231. MessageMemo->ScrollBars = ssVertical;
  232. MessageMemo->Anchors = TAnchors() << akLeft << akRight << akTop; //akBottom;
  233. MessageMemo->Color = clBtnFace;
  234. MessageMemo->Lines->Text = MoreMessages->Text;
  235. Result->MessageMemo = MessageMemo;
  236. TMoreButton * MoreButton = new TMoreButton(Result);
  237. MoreButton->Parent = Result;
  238. MoreButton->Panel = MessageMemo;
  239. MoreButton->Name = "MoreButton";
  240. MessageMemo->TabOrder = static_cast<short>(MoreButton->TabOrder + 1);
  241. ButtonControls[ButtonControlsCount] = MoreButton;
  242. ButtonControlsCount++;
  243. }
  244. int ButtonGroupWidth = 0;
  245. if (ButtonControlsCount > 0)
  246. {
  247. ButtonGroupWidth = ButtonWidth * ButtonControlsCount +
  248. ButtonSpacing * (ButtonControlsCount - 1);
  249. }
  250. int MoreMessageWidth = (MoreMessages != NULL ?
  251. MulDiv(mcMoreMessageWidth, DialogUnits.x, 4) : 0);
  252. int MoreMessageHeight = (MoreMessages != NULL ?
  253. MulDiv(mcMoreMessageHeight, DialogUnits.y, 8) : 0);
  254. int AClientWidth =
  255. (IconTextWidth > ButtonGroupWidth ? IconTextWidth : ButtonGroupWidth) +
  256. HorzMargin * 2;
  257. Result->ClientWidth = (AClientWidth > MoreMessageWidth ?
  258. AClientWidth : MoreMessageWidth);
  259. Result->ClientHeight = IconTextHeight + ButtonHeight + VertSpacing +
  260. VertMargin * 2 + MoreMessageHeight;
  261. Result->Left = (Screen->Width / 2) - (Result->Width / 2);
  262. Result->Top = (Screen->Height / 2) - (Result->Height / 2);
  263. if (DlgType != mtCustom)
  264. {
  265. Result->Caption = LoadResourceString(Captions[DlgType]);
  266. }
  267. else
  268. {
  269. Result->Caption = Application->Title;
  270. }
  271. if (IconID != NULL)
  272. {
  273. TImage * Image = new TImage(Result);
  274. Image->Name = "Image";
  275. Image->Parent = Result;
  276. Image->Picture->Icon->Handle = LoadIcon(0, IconID);
  277. Image->SetBounds(HorzMargin, VertMargin, 32, 32);
  278. }
  279. TLabel * Message = new TLabel(Result);
  280. Result->Message = Message;
  281. Message->Name = "Message";
  282. Message->Parent = Result;
  283. Message->WordWrap = true;
  284. Message->Caption = Msg;
  285. Message->BoundsRect = TextRect;
  286. Message->BiDiMode = Result->BiDiMode;
  287. int ALeft = IconTextWidth - TextRect.Right + HorzMargin;
  288. if (Message->UseRightToLeftAlignment())
  289. {
  290. ALeft = Result->ClientWidth - ALeft - Message->Width;
  291. }
  292. Message->SetBounds(ALeft, VertMargin, TextRect.Right, TextRect.Bottom);
  293. if (Result->MessageMemo != NULL)
  294. {
  295. Result->MessageMemo->BoundsRect = TRect(Message->Left,
  296. Message->Top + Message->Height + VertSpacing,
  297. Result->ClientWidth - HorzMargin,
  298. Message->Top + Message->Height + VertSpacing + MoreMessageHeight);
  299. }
  300. int X = (Result->ClientWidth - ButtonGroupWidth) / 2;
  301. for (int i = 0; i < ButtonControlsCount; i++)
  302. {
  303. ButtonControls[i]->SetBounds(X,
  304. IconTextHeight + VertMargin + VertSpacing + MoreMessageHeight,
  305. ButtonWidth, ButtonHeight);
  306. X += ButtonWidth + ButtonSpacing;
  307. }
  308. return Result;
  309. }
  310. //---------------------------------------------------------------------------
  311. TForm * __fastcall CreateMoreMessageDialog(const AnsiString & Msg,
  312. TStrings * MoreMessages, TMsgDlgType DlgType, TMsgDlgButtons Buttons,
  313. TQueryButtonAlias * Aliases, unsigned int AliasesCount)
  314. {
  315. return TMessageForm::Create(Msg, MoreMessages, DlgType, Buttons,
  316. Aliases, AliasesCount);
  317. }