Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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 в его методах к главному окну программы:

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;
, PostStrThreadMessage - надстройка над PostThreadMessage, переделывающая строку в PChar (StrNew), а уж в WndProc главного окна посылается сообщение UM_SetUserText в apiшное окошко:

 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.89 MB
Время: 0.063 c
14-1100918820
DelphiN!
2004-11-20 05:47
2004.12.12
Отловить хакера


1-1101804989
Серж_Евдокимов
2004-11-30 11:56
2004.12.12
Программно выбрать папку в ShellTreeView..


1-1101366227
Denmin
2004-11-25 10:03
2004.12.12
Как передать фокус из DBEdit на SpeedButton, из DBMemo в DBEdit ?


3-1100446917
kein
2004-11-14 18:41
2004.12.12
копирование из базы в базу


1-1100774315
Саша
2004-11-18 13:38
2004.12.12
Цвет выделенных ячеек в StringGrid





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский