Форум: "WinAPI";
Текущий архив: 2004.12.12;
Скачать: [xml.tar.bz2];
ВнизПочему DispatchMessage выдает AV? Найти похожие ветки
← →
Aleksandr. (2004-10-26 13:29) [0]в процерурке создается apiшное окошко для текстов сообщений, отдельный поток, ему передается эвент, и основной поток переходит в ожидание установки события:
P:=StrNew(PChar("UpdThread"));
try
A:=CreateEvent(nil,true,false,P);
try
try
FUpdator.StopEvent:=A;
FUpdator.Resume;
repeat
case MsgWaitForMultipleObjects(1,A,false,2000,QS_AllINPUT) of
Wait_Object_0 : if FUpdator.Stopped then
Break;
else while Peekmessage(M, 0, 0, 0, PM_REMOVE) do begin
TranslateMessage(M);
DispatchMessage(M)
end;
end
until FUpdator.Stopped
finally
CloseHandle(A)
end
Так вот DispatchMessage в какой-то момент начинает выдавать EAccessViolation. Сообщение, которое при этом обрабатывается, является пользовательским UM_SetUserText, пересылаемым окну, рисующему сообщения. Сообщения посылаются из потока Updator в его методах к главному окну программы:, PostStrThreadMessage - надстройка над PostThreadMessage, переделывающая строку в PChar (StrNew), а уж в WndProc главного окна посылается сообщение UM_SetUserText в apiшное окошко:
procedure TUpdator.DoOnStart(Msg: string; Step: Integer;
const Cnt: Integer);
var
s : string;
begin
s:=Msg+"$"+IntToStr(Step)+":"+IntToStr(Cnt);
if FMsgHandle<>0 then
PostStrThreadMessage(FMsgHandle,UM_UpdatorStep,s)
end;
if WaitFormHandle<>0 then begin
PostStrMessage(WaitFormHandle,WM_SetUserText,MsgText);
PostMessage(WaitFormHandle,WM_Paint,0,0)
end
которое просто рисует полученный PChar и освобождает его. Никак не могу допереть, почему DispatchMessage в итоге всего этого выдает AV.
← →
Digitman © (2004-10-26 13:38) [1]у тебя s - лок.переменная, время жизни которой равно времени жизни п/программы, где она объявлена
в то же время п/программа выполняет асинхр.вызов PostMessage, передавая параметром адрес этой переменной
поскольку PostMessage - асинхр.ф-ция, она ставит сообщение в очередь адресата и тут же завершается, в рез-те чего переменная s перестает существовать
на момент когда адресат начинает обработку посланного ему асинхр.сообщения, адрес строки, фигурирующий параметром сообщения, уже представляет собой ссылку в "никуда"
для подобных целей следует использовать синхронную посылку сообщений (SendMessage)
← →
Aleksandr. (2004-10-26 13:50) [2]Digitman © :
Так я же строку переделываю в PChar:
procedure PostStrMessage(aHandle : HWND; Msg : integer; S : string; const wP : integer=0);
var
P : PChar;
begin
P:=StrNew(PChar(s));
PostMessage(aHandle,Msg,wP,Integer(P))
end;
Разве выделенная StrNew память тоже убъется?
← →
Digitman © (2004-10-26 14:01) [3]здесь - нет
приведи точную декларацию/реализацию PostStrThreadMessage()
← →
Aleksandr. (2004-10-26 14:21) [4]Сорри, соседнюю процедурку скопировал. Код тот же:
procedure PostStrThreadMessage(aHandle : HWND; Msg : integer; S : string; const wP : integer=0);
var
P : PChar;
begin
P:=StrNew(PChar(s));
PostThreadMessage(aHandle,Msg,wP,Integer(P))
end;
← →
clickmaker © (2004-10-26 14:41) [5]
> [4] Aleksandr. (26.10.04 14:21)
Вроде все верно. Попробуй LocalAlloc + CopyMemory вместо StrNew
← →
Digitman © (2004-10-26 14:45) [6]
> Сообщение, которое при этом обрабатывается, является пользовательским
> UM_SetUserText
приводи полный код обработчика
← →
Aleksandr. (2004-10-26 15:31) [7]Digitman © :
Привожу. Функция, сажаемая апишному окну на обработчик. В interface объявлены глобальные переменные MainHandle, WaitFormHandle - при создании формы в них заносится хэндл родительского окна апишного окошка, и непосредственно API-окошка. В implementation глобальная типизированная константа FWaitText, хранящая содержимое последнего выведенного текста, и WaitWidth, хранящая заданную при создании ширину.
implementation
const
FWaitText : string="";
WaitWidth : integer=300;
function WindowProc(wnd:HWND; Msg : Integer; Wparam:Wparam; Lparam:Lparam) : Lresult; stdcall;
var
R : TRect;
DC : HDC;
rgn : HRGN;
s : string;
P : size;
Buf : PChar;
begin
case msg of
wm_Destroy : begin
...
FWaitText:="";
MainHandle:=0;
WaitFormHandle:=0
end;
wm_Activate,
wm_SetFocus,
wm_ActivateApp,
wm_MouseActivate,
wm_NCLButtonDown :
begin
PostMessage(WaitformHandle,wm_SetUserText,Integer(StrNew(PChar(FWaitText))),0);
Result:=0
end;
um_SetUserText :
begin
Result:=0;
DC:=GetDC(WaitFormHandle);
try
rgn:=CreateRectRgn(0,0,WaitWidth,70);
try
SetWindowRgn(WaitFormHandle,rgn,false);
FillRgn(DC,rgn,RGB(255, 0, 0));
R.Left:=0;
R.Top:=10;
R.Right:=WaitWidth;
R.Bottom:=70;
s:="";
repeat
s:=s+" ";
Buf:=StrNew(PChar(S));
try
GetTextExtentPoint32(DC,Buf,length(s),P)
finally
StrDispose(Buf)
end
until P.cx>=WaitWidth-2;
Buf:=StrNew(PChar(s));
try
DrawText(DC,PChar(Buf),-1,R,dt_Center+dt_VCenter);
finally
StrDispose(Buf)
end;
// залили пробелами по ширине, а то мусор от прежней записи остается
s:=StrPas(PChar(wParam));
StrDispose(PChar(wParam));
// получили текст сообщения
FWaitText:=s;
Buf:=StrNew(PChar(s));
try
DrawText(DC,Buf,-1,R,dt_Center+dt_VCenter+DT_END_ELLIPSIS)
finally
StrDispose(Buf)
end
finally
DeleteObject(RGN)
end
finally
ReleaseDC(Wnd,DC)
end;
PostMessage(WaitFormHandle,wm_LButtonDown,0,0)// а это сообщение, чтобы она фокус получила
end
else
Result:=DefWindowProc(wnd,msg,wparam,lparam)
end
End;
← →
Digitman © (2004-10-26 16:01) [8]ты трассировал пошагово тело обработчика um_SetUserText в контексте Windowproc() ? какая конкретно строчка возбуждает искл-е ?
← →
clickmaker © (2004-10-26 16:15) [9]
> PostMessage(aHandle,Msg,wP,Integer(P))
> s:=StrPas(PChar(wParam));
Передаешь строку в lParam, а ловишь в wParam
← →
Aleksandr. (2004-10-26 16:29) [10]clickmaker © :
Опять ввел в заблуждение. Когда комментарии писал, потер текст и добил вручную. Конечно lParam:
s:=StrPas(PChar(lParam));
StrDispose(PChar(lParam));
// получили текст сообщения
Digitman © :
В том-то и дело, что она там не создает ошибок. В смысле, я ставлю точку остановка на DispatchMessage, жму F7, и он тупо проскакивает на следующую строчку. А DispatchMessage разве тоже вызовет этот обработчик?
← →
Digitman © (2004-10-26 16:29) [11]
> clickmaker © (26.10.04 16:15) [9]
вот тебе не лень анализировать кучу чужого кода)
автор-то палец о палец не ударил, мол, AV при вызове диспетчера - и все тут .. чужие мозги - они всегда нахалявку)
← →
Digitman © (2004-10-26 16:31) [12]
> А DispatchMessage разве тоже вызовет этот обработчик?
а какой еще обработчик он, по-твоему, вызовет, кроме этого ?
какой установлен, такой и вызовет ..
← →
Aleksandr. (2004-10-26 16:31) [13]Digitman © :
Лозунг коммунистов знаете? Богатый должен делиться :). Кому Бог дал больше мозгов и меньше работы, тот и делится.
← →
Aleksandr. (2004-10-26 16:32) [14]Digitman © :
Я-то, наивный, полагал, что TranslateMessage...
← →
clickmaker © (2004-10-26 16:55) [15]
> [14] Aleksandr. (26.10.04 16:32)
> Digitman © :
> Я-то, наивный, полагал, что TranslateMessage...
TranslateMessage переводит виртуальные коды клавиш (те, что VK_) в символьные. Основную работу делает DispatchMessage
← →
Aleksandr. (2004-10-26 17:48) [16]clickmaker © :
Век живи, век учись. Буду знать...
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2004.12.12;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.036 c