Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 2 964

/ вопрос открыт /

Доброго времени суток, уважаемые эксперты!

Подскажите, как решить следующую проблему:

Есть расчет, который выполняется в потоке. В нем(алгоритме расчета) куча ShowMessage, которые теперь отрабатывают не нужным образом.

Как можно перехватить сигнал от ShowMessage, чтобы переопределить этот вызов на sendmessage или postmessage?

Aндрей Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: 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ндрей

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ндрей

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ндрей

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ндрей

Aндрей (статус: 1-ый класс), 7 июля 2009, 13:17 [#7]:

Спасибо, с "public class var " разобрался

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:25
Выполнено за 0.02 сек.