| 
| 
 | Вопрос # 2 964/ вопрос открыт / | 
 |  Доброго времени суток, уважаемые эксперты!
 Подскажите, как решить следующую проблему:
 
 Есть расчет, который выполняется в потоке. В нем(алгоритме расчета) куча ShowMessage, которые теперь отрабатывают не нужным образом.
 
 Как можно перехватить сигнал от ShowMessage, чтобы переопределить этот вызов на sendmessage или postmessage?
 
|  |   Вопрос задал: Aндрей (статус: 1-ый класс)Вопрос отправлен: 2 июля 2009, 10:09
 Состояние вопроса: открыт, ответов: 1.
 |  Ответ #1. Отвечает эксперт: Вадим К Здравствуйте, Aндрей!Есть очень простой и быстрый метод. В классе потока опредеяем метод Showmessage. Теперь поток будет вызывать свой метод вместо функции с юнита dialogs (вроде там она находиться). Само объявление лучше поместить в private часть в виде
 procedure ShowMessage(msg:string); и жмем Crtl+Shift+C
 теперь уже можно например сделать логирование в файл. Все вызовы в пределах потока будут перехвачены. (если конечно в Вашем коде нет чудес).
 Теперь задача номер два - передать строку с потока в основную программу. Поступим самым простым способом.
 в коде метода ShowMessage пишем такую реализацию
 SendMessage(MainHandle, WM_USER, integer(msg), 0);
 MainHandle - это ещё одно поле типа THandle, куда надо передать с главной формы (или какая форма будет принимать сообщения от потока её хендл - просто свойство form1.handle. Это хорошо сделать при инициализации потока).
 Теперь прием сообщения в основном окне.
 заводим приватный метод формы
 procedure MyMessage(var msg:TMessage); message WM_USER;
 и жмем снова Crtl+Shift+C.
 В процедуре пишем что то вида
 memo1.lines.add(string(msg.wparam));
 или выводим мессадж.
 
 Использовать PostMessage в данном случае не рекомендованно - postmessage после отправки сообщения продолжает свою работу и строка может поменяться (а мы передаем указатель на строку...)
 
|  | Ответ отправил: Вадим К (статус: Академик)Время отправки: 2 июля 2009, 12:21
 Оценка за ответ: 5
 |  
 Мини-форум вопросаВсего сообщений: 7; последнее сообщение — 7 июля 2009, 13:17; участников в обсуждении: 2. 
|   | Aндрей (статус: 1-ый класс), 6 июля 2009, 16:37 [#1]:Попробовал сделать так, как Вы описали: 
 type TSmartThread = class (TThread)
 private MainHandle: THandle;
 private procedure ShowMessage(const Msg: string);
 private function MessageDlg(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx: Longint): Integer;
 end;
 
 constructor TSmartThread.Create( AForm: TForm; Manager: IStationManager;
 ButtonRunCalculate, ButtonBreakCalculate, ButtonFormClose: TControl );
 begin
 Self.MainHandle := AForm.Handle;
 end;
 
 function TSmartThread.MessageDlg(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx: Longint): Integer;
 begin
 SendMessage(Self.MainHandle, WM_USER, integer(msg), 0);
 end;
 
 
 procedure TSmartThread.ShowMessage(const Msg: string);
 begin
 SendMessage(Self.MainHandle, WM_USER, integer(msg), 0);
 end;
 
 //====================== Форма главная
 ...
 private procedure MyMessage(var msg:TMessage); message WM_USER;
 ...
 procedure TFormManager.MyMessage(var msg: TMessage);
 var str_msg: string;
 begin
 
 str_msg := (string(msg.wparam));
 end;
 
 
 Но при отработке все осталось как было: т.е. в классе, обект которого создается для расчета
 
 function TCalculatorBase.BoilerDescription(const file_path: string; BoilerHeatLoad: Double) : Double;
 begin
 //                ShowMessage('Проверьте, пожалуйста, правильность введенных данных!');
 MessageDlg('Проверьте, пожалуйста, правильность введенных данных!',
 mtError , [mbOK], 0);
 
 end;
 
 Отрабатывает сначала вывод окна с неправильными размерами.
 А в методы, переопределенные в классе TSmartThread, заходит только в MessageDlg и то после вывода окна сообщения, а в ShowMessage не заходит вообще никогда (поэтому в примере кода он закомментирован).
 
 И все равно кидает ошибки: неверный дескриптор и т.п.
 
 Что я делаю неверно?
 |  
|   | Вадим К (статус: Академик), 6 июля 2009, 16:47 [#2]:странно, должно вообще то заходить. поставьте точку останова на SendMessage(Self.MainHandle, WM_USER, integer(msg), 0); и посмотрите, заходит ли. А также в юните с тредом можно попробовать с списка uses удалить модуль Dialogs (в профилактических целях). Галочка "подтверждения прочтения" - вселенское зло. |  
|   | Aндрей (статус: 1-ый класс), 6 июля 2009, 17:23 [#3]:В SendMessage не заходит, Удалил из uses связь с Dialogs - никаких изменений
 
 Может, все таки что-то нагородил. Еще раз опишу, что сделал:
 1. В классе-потомке Thread объявил точно такой же как и в Dialogs метод ShowMessage(const Msg: string);
 1.1. Добавил в него строку
 SendMessage(Self.MainHandle, WM_USER, Integer(Msg), 0);
 
 2. В форме, в которой создаю поток (MainHandle - это Handle этой формы), объявляю
 private procedure MyMessage(var msg:TMessage); message WM_USER;
 
 там делаю свою обработку
 
 Все ли верно?
 |  
|   | Вадим К (статус: Академик), 6 июля 2009, 17:49 [#4]:да всё выглядит правдоподобно. и должно работать. Точка останова в ShowMessage не срабатывает?
 тогда следует попробовать в тестовых целях написать вызов как self.ShowMessage либо либо сделать свое имя. Если и в этом случае не зайдет - выкладывайте полные исходники (кстати, у нас сервис появился, так что можно там. А сюда только ссылку.
 Галочка "подтверждения прочтения" - вселенское зло. |  
|   | Aндрей (статус: 1-ый класс), 7 июля 2009, 10:12 [#5]:Выдает ошибки: [DCC Error] GUI.Dialogs.pas(25): E2065 Unsatisfied forward or external declaration: 'TGUIMessageDialogs.ShowMessage'
 [DCC Error] GUI.Dialogs.pas(26): E2065 Unsatisfied forward or external declaration: 'TGUIMessageDialogs.MessageDlg'
 
 Что неверно в этом коде??:
 
 unit GUI.Dialogs;
 
 
 
 interface
 
 uses
 Dialogs;
 
 
 
 type
 TGUIMessageDialogs = class
 
 private class var FInstance : TGUIMessageDialogs;
 
 public class function getProfile (): TGUIMessageDialogs;
 public class procedure FreeProfile();
 public class function CreateProfile (MainHandle: THandle): TGUIMessageDialogs;
 
 
 public class var procedure ShowMessage(const Msg: string);
 public class var function  MessageDlg (const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx: Longint): Integer;
 
 private class var FHandle: THandle;
 end;
 
 
 
 implementation
 
 uses
 Windows,
 Messages;
 
 { TGUIMessageDialogs }
 
 class procedure TGUIMessageDialogs.FreeProfile();
 begin
 Self.FInstance.Free;
 Self.FInstance := nil;
 
 Self.FHandle := 0;
 end;
 
 class function TGUIMessageDialogs.GetProfile: TGUIMessageDialogs;
 begin
 if (Self.FInstance  = nil)
 or (Self.FHandle    = 0  )
 then Assert(False, 'TGUIMessageDialogs was not created');
 
 Result := Self.FInstance;
 end;
 
 
 class function TGUIMessageDialogs.MessageDlg(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx: Integer): Integer;
 begin
 SendMessage(TGUIMessageDialogs.FHandle, WM_USER, Integer(Msg), 0);
 end;
 
 class procedure TGUIMessageDialogs.ShowMessage(const Msg: string);
 begin
 SendMessage(TGUIMessageDialogs.FHandle, WM_USER, Integer(Msg), 0);
 end;
 
 class function TGUIMessageDialogs.CreateProfile(MainHandle: THandle): TGUIMessageDialogs;
 begin
 if (Self.FInstance = nil)
 then begin
 Self.FInstance := TGUIMessageDialogs.Create();
 Self.FHandle   := MainHandle;
 end;
 
 Result := Self.FInstance;
 end;
 
 
 
 end.
 |  
|   | Вадим К (статус: Академик), 7 июля 2009, 11:39 [#6]:вы хорошо понимаете суть строки "public class var "? Судя по коду, слишком много программировали на шарпе. или чем то подобном (java). public и private не обязательно перед каждым объявлением писать. Только делаете код некрасивее. Некрасивый код - ошибкам легче прятаться.
 Галочка "подтверждения прочтения" - вселенское зло. |  
|   | Aндрей (статус: 1-ый класс), 7 июля 2009, 13:17 [#7]:Спасибо, с "public class var " разобрался |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |