Yorumları: 1.460
Konuları: 80
Kayıt Tarihi: 05-08-2016
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 11.868 Üstad
06-09-2017, Saat: 16:29
(Son Düzenleme: 06-09-2017, Saat: 16:30, Düzenleyen: Tuğrul HELVACI.)
Forumda gördüğüm Windows mesajlaşma ile ilgili bir konuya müteakiben; +10 puan kıymetinde bir soru yönlendirmek istedim sizlere. Bu eğlencelik aktivitede sizlerden beklenenler aşağıdaki gibidir:
- 2 adet VCL uygulamanız olacak.
- Her iki uygulamada da formunuz üzerinde bir adet button olacak.
- Birinci uygulamanın button'una basıldığında 30 saniye uyuma kodu yazacaksınız. Aynı zamanda bu uygulama üzerinde diğer uygulamadan gönderilecek olan mesajı yakalayacaksınız ve ShowMessage ile ekrana bir bildirim mesajı çıkartacaksınız.
- Ardından ikinci uygulamanın buttonuna basacaksınız ve birinci uygulamanın ana penceresinin handle'ını bulacak, ardından ilgili pencereye sizin belirlediğiniz bir mesajı göndereceksiniz.(PostMessage ile ve SendMessage ile)
- Ne olduğunu ve nedenlerini izah edeceksiniz.
- İkinci uygulamanız kilitlendi ise, bunu nasıl aşabileceğinizi belirteceksiniz.
Başarılar ve iyi eğlenceler
Doğru cevabı ilk veren arkadaşımız +10 puanı alacak. Diğer arkadaşlarımıza da teselli puanları vereceğim
Not: Mesajınızı bir kerede doğru göndermeye gayret edin. Editlediğiniz mesaj doğru da olsa +10 puan veremeyeceğim.
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
Yorumları: 15
Konuları: 0
Kayıt Tarihi: 03-09-2017
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 299 Acemi
(06-09-2017, Saat: 16:29)Tuğrul HELVACI Adlı Kullanıcıdan Alıntı:
- Her iki uygulamada da formunuz üzerinde bir adet button olacak.
Button ne kadar büyükse proje de o kadar büyük olacak mı peki?
Me on the move..
Yorumları: 1.460
Konuları: 80
Kayıt Tarihi: 05-08-2016
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 11.868 Üstad
(06-09-2017, Saat: 16:46)The_aLiEn Adlı Kullanıcıdan Alıntı: (06-09-2017, Saat: 16:29)Tuğrul HELVACI Adlı Kullanıcıdan Alıntı:
- Her iki uygulamada da formunuz üzerinde bir adet button olacak.
Button ne kadar büyükse proje de o kadar büyük olacak mı peki?
Tabii
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
Yorumları: 15
Konuları: 0
Kayıt Tarihi: 03-09-2017
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 299 Acemi
06-09-2017, Saat: 17:34
(Son Düzenleme: 06-09-2017, Saat: 17:43, Düzenleyen: TescilsizUzman.)
Tutamadım kendimi, servise binmedim
1. uygulama:
const
WM_P2 = WM_User + 11863;
cSecond = 30;
cSleepTime = cSecond * 1000;
type
Tp1Frm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private procedure WM_P2_Message(var msg: TMessage); message WM_P2;
public
end;
procedure Tp1Frm1.WM_P2_Message(var msg: TMessage);
begin
ShowMessage('WM_P2_Message mesajı işleniyor');
// some code..
ShowMessage('WM_P2_Message mesajı işlendi');
end;
procedure Tp1Frm1.Button1Click(Sender: TObject);
begin
Sleep(cSleepTime);
end;
Bu da 2. uygulama:
const
WM_P2 = WM_User + 11863;
procedure TForm2.Button1Click(Sender: TObject);
var
p1Handle: HWND;
begin
p1Handle := FindWindow('Tp1Frm1', nil);
if p1Handle <> 0 then
if IsWindow(p1Handle) then
PostMessage(p1Handle, WM_P2, 0, 0);
//SendMessage(p1Handle, WM_P2, 0, 0);
ShowMessage('DONE');
end;
Şimdi gelelim açıklamalara:
Senkron ve asenkron kavramlarını hemen hepimiz biliyoruz değil mi? ( Aslında bu cümleden sonra devam etmeme gerek olmamalı ) )
API'leri bilmiyorsak hemen dökümana başvuruyoruz; kaçamazsınız...
PostMessage
SendMessage
PostMessage der ki, HWND parametresi ile verdiğin pencerenin mesaj kuyruğuna, verdiğin mesajı, verdiğin parametrelerle BIRAKIRIM, MESAJIN İŞLENİP İŞLENMEDİĞİYLE İLGİLENMEM, GERİ DÖNERİM.
SendMessage da der ki, HWND parametresi ile verdiğin pencerenin mesaj kuyruğuna, verdiğin mesajı, verdiğin parametrelerle GÖNDERİRİM VE MESAJIN İŞLENMESİNİ BEKLERİM.
Neler olduğu ve neden olduğu tamemen bu bekleme/beklememe mekanizmasının çeşitli kombinasyonları. Şöyle örneklendireyim:
Sleep(30*1000) gibi bir uyuma verdiğinizde ilgili thread bloklanacak olduğu için, varsa, o thread'in mesaj kuyruğu da işlenemeyecektir.
Bu mesaj kuyruğuna SendMessage ile gönderilen tüm mesajlar, thread bloklandığı için işlenemeyecek; gönderici tarafı da alıcıdan bir işlendi cevabı beklediği ve alamadığı için SendMessage içinde bloklanacaklardır.
Bu mesaj kuyruğuna PostMessage ile gönderilen tüm mesajlar, thread bloklandığı için işlenemeyecek FAKAT, gönderici tarafı herhangi bir işlendi cevabı beklemediği için bloklanmayacak ve çalışmasına devam edecektir.
Her iki durum için de, Sleep süresi bitip ilgili thread tekrar tarifelendiğinde alıcı taraftaki kuyruk tüketilmeye devam edilecek ve kuyruktaki mesajlar işlenecektir.
Nasıl aşılabileceğine dair bilgiyi çoktan verdim aslında )
(06-09-2017, Saat: 17:25)Tuğrul HELVACI Adlı Kullanıcıdan Alıntı: (06-09-2017, Saat: 16:46)The_aLiEn Adlı Kullanıcıdan Alıntı: Button ne kadar büyükse proje de o kadar büyük olacak mı peki?
Tabii
Abi buyur o zaman )
--
Me on the move..
Yorumları: 24
Konuları: 0
Kayıt Tarihi: 15-04-2017
Aktif Kullandığınız Delphi Sürümü:
- Delphi 10.2
- Delphi 7
- Lazarus / FPC
Rep Puanı: 210 Acemi
06-09-2017, Saat: 17:48
(Son Düzenleme: 06-09-2017, Saat: 17:55, Düzenleyen: TescilsizUzman.)
(06-09-2017, Saat: 16:29)Tuğrul HELVACI Adlı Kullanıcıdan Alıntı: Forumda gördüğüm Windows mesajlaşma ile ilgili bir konuya müteakiben; +10 puan kıymetinde bir soru yönlendirmek istedim sizlere. Bu eğlencelik aktivitede sizlerden beklenenler aşağıdaki gibidir:
- 2 adet VCL uygulamanız olacak.
- Her iki uygulamada da formunuz üzerinde bir adet button olacak.
- Birinci uygulamanın button'una basıldığında 30 saniye uyuma kodu yazacaksınız. Aynı zamanda bu uygulama üzerinde diğer uygulamadan gönderilecek olan mesajı yakalayacaksınız ve ShowMessage ile ekrana bir bildirim mesajı çıkartacaksınız.
- Ardından ikinci uygulamanın buttonuna basacaksınız ve birinci uygulamanın ana penceresinin handle'ını bulacak, ardından ilgili pencereye sizin belirlediğiniz bir mesajı göndereceksiniz.(PostMessage ile ve SendMessage ile)
- Ne olduğunu ve nedenlerini izah edeceksiniz.
- İkinci uygulamanız kilitlendi ise, bunu nasıl aşabileceğinizi belirteceksiniz.
Başarılar ve iyi eğlenceler
Doğru cevabı ilk veren arkadaşımız +10 puanı alacak. Diğer arkadaşlarımıza da teselli puanları vereceğim
Not: Mesajınızı bir kerede doğru göndermeye gayret edin. Editlediğiniz mesaj doğru da olsa +10 puan veremeyeceğim.
Doğru anladım mı bilmiyorum ama şöyle bir şey mi olacaktı ?
unit Unit1; // Uyuyan
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
Const WM_USERMSG_UYAN = WM_USER + 999;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
procedure WMUSERMSGUYAN(Var Msg : TMessage);message WM_USERMSG_UYAN;
public
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
Sleep(30000);
end;
procedure TForm1.WMUSERMSGUYAN(var Msg: TMessage);
begin
Application.MessageBox('Uyan Uyan Uyan','Uyandırma Servisi',mb_iconinformation);
end;
end.
unit Unit2; // Uyandıran
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
Const WM_USERMSG_UYAN = WM_USER + 999;
type
TmyThread = Class(TThread)
private
FHnd : Hwnd;
Protected
procedure Execute; override;
Public
constructor Create(Const AHnd: THandle);
destructor Destroy; override;
End;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
public
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
Var
Hnd : Hwnd;
T : TmyThread;
begin
Hnd := FindWindow('TFORM1', 'UYUYAN GUZEL');
if Hnd <> 0 then
T := TmyThread.Create(Hnd);
end;
{ TmyThread }
constructor TmyThread.Create(const AHnd: THandle);
begin
Inherited Create(True);
FreeOnTerminate := True;
FHnd := AHnd;
Resume;
end;
destructor TmyThread.Destroy;
begin
inherited;
end;
procedure TmyThread.Execute;
begin
inherited;
SendMessage(FHnd, WM_USERMSG_UYAN, 0, 0);
end;
end.
1. Uyuyan uygulama kanal olmadan uyandırılmak istenince Tuğrul hocamın dediği gibi uyandıran kilitlendi. Sebebi sleep çağırısıyla windows uyuyan uygulamayı askıya alıp denetimi eşit veya daha yüksek önceliğe sahip diğer işlemlere geçirmesi. Uyandıran tarafından uyuyana geçilen Sendmessage windows un askıya aldığı uygulamaya ulaşmadığından uyandıran tarafından sendmessage dönüş değeri uyandırana dönmüyor.
2. Uyandıranın gönderimini Kanalla windows mesaj kuyruğuna ekleyince ve 30 saniyelik uyuma sona erince uyuyan uygulama mesajı aldı ve kilitlenme sorunu çözüldü.
Yorumları: 357
Konuları: 30
Kayıt Tarihi: 10-07-2017
Aktif Kullandığınız Delphi Sürümü:
- Delphi 10.3
- Lazarus / FPC
Rep Puanı: 4.211 Uzman
Arkadaşlar ben Bilgisyarımdan uzakta olduğum için cevap veremiyorum,ama nacizane fikrimi söyleyeyim,bence hocamın istediği fonksiyon SendMessageTimeout fonksiyonu.
Yorumları: 24
Konuları: 0
Kayıt Tarihi: 15-04-2017
Aktif Kullandığınız Delphi Sürümü:
- Delphi 10.2
- Delphi 7
- Lazarus / FPC
Rep Puanı: 210 Acemi
(06-09-2017, Saat: 18:45)savasabd Adlı Kullanıcıdan Alıntı: Arkadaşlar ben Bilgisyarımdan uzakta olduğum için cevap veremiyorum,ama nacizane fikrimi söyleyeyim,bence hocamın istediği fonksiyon SendMessageTimeout fonksiyonu.
Bencede hoca farklı bir yöntem istiyor velakin sendmessage api fonksiyonunu görünce aklıma başka bir sey gelmedi. Postmessage ile denemedim fakat ali en de iyi anlatmış.
Yorumları: 253
Konuları: 16
Kayıt Tarihi: 26-09-2016
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 3.279 Uzman
06-09-2017, Saat: 22:58
(Son Düzenleme: 06-09-2017, Saat: 23:57, Düzenleyen: ismailkocacan.
Sebep: memesi olacak
)
1. uygulamada Sleep ile thread bloklanıp, 2. uygulamadan da windows mesajı gönderilip aynı zamanda 2. uygulamanın donmaması/kilitlenmemesi isteniyorsa PostMessage ve SendMessage dışında SendMessageCallback callback fonksiyonu kullanılabilir.
SendMessageCallback fonksiyonu ile ilgili pencereye Windows mesajı gönderilir ve Windows procedure'ün çalışması beklenmeden hemen geriye dönülür.Windows procedure ilgili mesajı işledikten sonra yani çalıştıktan sonra, belirtilen callback fonksiyonu çağırarak mesajı işlediğini bildirir.
Dolayısı ile 1. uygulama Sleep ile bloklansa bile, 2. uygulamadan SendMessageCallback ile mesaj gönderildiğinde bir kilitlenme meydana gelmez.
Callback fonksiyon prototipi.
VOID CALLBACK SendAsyncProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ ULONG_PTR dwData,
_In_ LRESULT lResult
);
procedure SendAsyncProc(HWND: HWND; Msg: UINT; wParam: wParam;
dwData: ULONG_PTR; lResult: LRESULT);
begin
ShowMessage('mesaj işlendi');
end;
procedure TForm1.Button3Click(Sender: TObject);
var
p1Handle: HWND;
dwData: UIntPtr;
begin
p1Handle := FindWindow(nil, 'MainApp');
if p1Handle = 0 then exit;
if not IsWindow(p1Handle) then exit;
dwData := 31;
SendMessageCallback(p1Handle, WM_P2, 0, 0, @SendAsyncProc, dwData);
ShowMessage('DONE');
end;
Yorumları: 44
Konuları: 3
Kayıt Tarihi: 02-12-2016
Rep Puanı: 39 Başlangıç
Birinci Form
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
//Declare the message body name
const
Mymsg= 'delphican';
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
WProc: Pointer;
DelphicanMmsg: cardinal;
implementation
{$R *.dfm}
function NewWndProc(Handle: hWnd; Msg, wParam, lParam: Cardinal): LongInt; stdcall;
begin
if Msg= DelphicanMmsg then
begin
MessageBox(handle, 'Uygulama Mesajı', '', MB_OK);
Result:= 1;
end else
Result := CallWindowProc(WProc, Handle, Msg, wParam, lParam);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Sleep(30000);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
DelphicanMmsg:= RegisterWindowMessage(Mymsg);
end;
initialization
WProc := Pointer(SetWindowLong(Application.Handle, gwl_WndProc,
Integer(@NewWndProc)));
end.
İkinci Form
unit Unit2;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
const
Mymsg= 'delphican';
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
DelphicanMmsg: cardinal; //This is the actual handle of the message
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
PostMessage(HWND_BROADCAST, DelphicanMmsg, 0, 0);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
DelphicanMmsg:= RegisterWindowMessage(Mymsg);
end;
end.
Yorumları: 1.460
Konuları: 80
Kayıt Tarihi: 05-08-2016
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 11.868 Üstad
07-09-2017, Saat: 10:48
(Son Düzenleme: 07-09-2017, Saat: 10:49, Düzenleyen: Tuğrul HELVACI.)
Arkadaşlar, öncelikle ilginize teşekkür ederim. Bu kısım altında yorumda bulunan ve çözüm sunan tüm arkadaşlarımıza bir kısım puanlar verdim.
The_aLiEn arkadaşımıza uzun ve detaylı açıklamasından ötürü teşekkür ederim. SendMessageCallback API'sinden bahsetmediği için 2 puanını kırdım
ismailkocacan arkadaşımıza doğru çözümü sunduğu için teşekkür ederim. Tam puan.
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
|