Konuyu Oyla:
  • Derecelendirme: 5/5 - 2 oy
  • 1
  • 2
  • 3
  • 4
  • 5
Windows Mesajlaşma Sistemi Hk. Soru (+10 Puan)
#1
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 Smile

Doğru cevabı ilk veren arkadaşımız +10 puanı alacak. Diğer arkadaşlarımıza da teselli puanları vereceğim Shy

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...
WWW
Cevapla
#2
(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? Big Grin
Me on the move..
WWW
Cevapla
#3
(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? Big Grin

Big Grin Tabii
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#4
Tutamadım kendimi, servise binmedim Big Grin

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ı Smile) )

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 Smile)

(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? Big Grin

Big Grin Tabii

Abi buyur o zaman Smile)

   

--

   
Me on the move..
WWW
Cevapla
#5
(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 Smile

Doğru cevabı ilk veren arkadaşımız +10 puanı alacak. Diğer arkadaşlarımıza da teselli puanları vereceğim Shy

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ü.
96zSCR
Cevapla
#6
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.
Herhangi bir basit problem, hakkında yeterince toplantı yapılarak, çözümsüz hale getirilebilir.
https://play.google.com/store/apps/developer?id=ONGUN
WWW
Cevapla
#7
(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ış.
Cevapla
#8
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;

WWW
Cevapla
#9
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.
Cevapla
#10
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 Smile

ismailkocacan arkadaşımıza doğru çözümü sunduğu için teşekkür ederim. Tam puan. Wink
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla


Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  Soru : Interface mi, Abstract Class mı? uparlayan 3 3.926 24-08-2023, Saat: 20:15
Son Yorum: veteran
  [+10 Puan] String Manipülasyon İşlemleri Abdullah ILGAZ 16 12.541 20-04-2019, Saat: 00:48
Son Yorum: onurcan1977
  Dosya Bulma (Algoritmik Soru Serisi) yhackup 28 22.376 14-11-2018, Saat: 10:07
Son Yorum: engerex
  Tek dizi içinde öncelik sırası belirleme (+10 puan) Abdullah ILGAZ 4 5.067 29-11-2017, Saat: 12:07
Son Yorum: SimaWB
  Bir Record'un içini doldurma (+20 puan) Tuğrul HELVACI 21 19.259 05-10-2017, Saat: 16:33
Son Yorum: ismailkocacan



Konuyu Okuyanlar: 2 Ziyaretçi