Program Bir Kere Çalışsın Çalışıyorsa Onu Aktif Yapsın

Yazdığınız makaleleri ve üyelerimizin işine yarayacağını düşündüğünüz kodlarınızı gönderebilirsiniz. Bu foruma soru sormayın!
Cevapla
Kullanıcı avatarı
sabanakman
Kıdemli Üye
Mesajlar: 3077
Kayıt: 17 Nis 2006 08:11
Konum: Ah bi Antalya olaydı keşke (Ankara)

Program Bir Kere Çalışsın Çalışıyorsa Onu Aktif Yapsın

Mesaj gönderen sabanakman »

Herkese iyi çalışmalar;

Aslında bu konu formda defalarca ifade edildi ve bir arama yapıldığı zaman onlarca cevap bulunacaktır. Burada konu ile ilgili son bir toparlama bilgi vermek için bu yazıyı yazmak istedim.

Genelde bir program çalışıyorsa 2. defa çalışmasını engellemek için en sık karşılaşılan yöntem Mutex oluşturmak ve bunu kullanmak olacaktır. Progamımızın .dpr dosyasına (<-.dpr açıklaması için not eklendi):

Kod: Tümünü seç

// uses Windows, SysUtils, Dialogs
var hMyMutex : tHandle;
begin
  hMyMutex := CreateMutex(nil,FALSE,'Deneme');
  if (hMyMutex <> 0) then try
    if (GetLastError <> ERROR_ALREADY_EXISTS) then begin
      Application.Initialize;
      Application.CreateForm(TForm1,Form1);
      Application.Run;
    end else ShowMessage ('Program zaten çalışıyor');
  finally
    CloseHandle (hMyMutex);
  end else ShowMessage ('Program tanım oluşturmada hata : ' + IntToStr(GetLastError));
end.
kodunu yazdığımız zaman bu işlem gerçekleşmektedir. Peki ama çalışan programı ekranda aktif hale getirmek istiyorsak ne yapmalıyız. Bu daha çok sistem saatinin yanında simge halinde bekleyen (system try) programlar için yaygındır. Diyelimki gelişmiş bir saat programı yazıldı ve progamı 1'den fazla açmak pek mantıklı durmuyor. Ama 2., 3. defa çalıştırılmaya kalkışıldığında orada çalışır halde bekleyen programı aktif yapmak istiyorsak o zaman farklı bir metot kullanmak gerekiyor. FindWindow(ClassName,Caption) API fonksiyonu işimizi görecektir. Bu fonksiyon başlığını (Caption) verdiğimiz programın Handle numarasını verecektir. Hatta sınıf ismini de (ClassName) kullanarak daha isabetli bir arama yapılabilir. Çünkü bir windows oturumunda bir çok program penceresi çalıştırılmaktadır ve bu pencere başlıkları tesadüfen aynı değere sahip olabilir. Bir arama sonucunda istenmeyen başka bir program bulunduğunda ise bizim programımız açılmayacaktır. Bu durumu ortadan kaldırmak için daha açıklayıcı Caption değeri verilmesi yeterli olsa da ClassName'i de işin içine katmanın daha şık olacağı kanaatindeyim. Mesela yazdığımız programın Caption değeri Saat ve sınıf adı da TFormSaat ise bu programı FindWindow(nil,'Saat') fonksiyonuyla testpit edebileceğimiz gibi FindWindow('TFormSaat','Saat') fonksiyonuyla da bulabiliriz ve 2. yöntem bizi daha doğru sonuca götürecektir. Delphi dilinin bir güzel özelliği de oluşturulan sınıfları Windows için aynı sınıf isminde oluşturmasıdır. Bir nesnenin Windows sınıf ismini

Kod: Tümünü seç

function WinClassName(const Handle:THandle):String;
var Buffer: array[0..MAX_PATH] of Char;
begin
  Windows.GetClassName(Handle,Buffer,MAX_PATH);
  Result:=Buffer;
end;
fonksiyonuyla öğrenebiliriz. Mesela ShowMessage(WinClassName(FormSaat.Handle)); kodu ile ekrana TFormSaat mesajı gelecektir. Şimdi bu bilgiler doğrultusunda çalışan programı aktif hale getirelim. Yine .dpr dosyamızda kod yazacağız.

Kod: Tümünü seç

// uses Windows, SysUtils, Dialogs
const SaatCaption='Saat';
var ProgHwnd:THandle; 
begin
  ProgHwnd:=FindWindow(PChar(String(TFormSaat.ClassName)),SaatCaption);
  {ProgHwnd:=FindWindow(nil,SaatCaption); {<-bu da iş görür ancak Caption çakışmasını engellemek gerek :) }
  if ProgHwnd=0 then begin
    Application.Initialize;
    Application.CreateForm(TFormSaat, FormSaat);
    FormSaat.Caption:=SaatCaption;
{FormSaat formu tasarım anında başlığı boş olmalıdır, yoksa delphi ekranı açıkken sorun oluşabilir. ProgHwnd:=FindWindow... kodu delphi tasarımında olan formu bularak istenmeyen bir durum oluşturabilir.}
    Application.Run;
  end else begin
    SetForegroundWindow(ProgHwnd); //<-Öne getir
  end;
end.
Böylelikle çalışır durumda bulunan proje varsa bu aktif hale gelecek, yoksa da o zaman program normal çalışmasına devam edecektir. Herkese çalışmalarında başarılar dilerim.

------------------------------------------------------------------------------------------
Not:Projede çalışılan formların oluşturulduğu

Kod: Tümünü seç

program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.
benzeri kodlara sahip bir proje dosyası bulunmaktadır. Bu dosya projenin ana dosyasıdır ve Project->View Source menü seçeneği ile ulaşılabilinir.
Şaban Şahin AKMAN
_________________
Derin olan kuyu değil kısa olan iptir. - .
Kullanıcı avatarı
haydarxxx
Üye
Mesajlar: 668
Kayıt: 09 May 2005 11:31
Konum: izmir

Mesaj gönderen haydarxxx »

Hocam ben makaleyi yeni gördüm forumda da daha önce aramıştım bu konu ile ilgili ama tam bir çözüm bulammaıştım kaldıki sizde belirtmişsiniz
Aslında bu konu formda defalarca ifade edildi ve bir arama yapıldığı zaman onlarca cevap bulunacaktır
Fakat bu kodları hangi eventlere yazıyoruz nasıl kullanacağız.Bununlada ilgili biligilendirme yapabilirmisiniz.Yada yapabilecek bir arkadaş. :roll:
khanco
Üye
Mesajlar: 226
Kayıt: 01 Eki 2007 04:39
Konum: İzmir
İletişim:

Mesaj gönderen khanco »

pas dosyasına değil dpr (proje) dosyasına yazıyor.
Kullanıcı avatarı
Nick_
Üye
Mesajlar: 122
Kayıt: 01 Eki 2007 09:28
Konum: Konya

Re: Program Bir Kere Çalışsın Çalışıyorsa Onu Aktif Yapsın

Mesaj gönderen Nick_ »

Pekı Programımız System Tray da calısıyor ıse formu nasıl gosterebılırız? anlattıgınız bu kodlar sadece form acıksa ve arkada kalmıssa öne getırıyor. programımız System Trayda calısırken formu acmıyor.
Bilmemek ayıp değil öğrenmek isteyene öğretmemek ayıp:)
Kullanıcı avatarı
Battosai
Üye
Mesajlar: 1316
Kayıt: 01 Eki 2007 12:02
Konum: Ankara

Re: Program Bir Kere Çalışsın Çalışıyorsa Onu Aktif Yapsın

Mesaj gönderen Battosai »

Pekı Programımız System Tray da calısıyor ıse formu nasıl gosterebılırız?
Application.Restore komutu ile olması lazım....
Kullanıcı avatarı
Nick_
Üye
Mesajlar: 122
Kayıt: 01 Eki 2007 09:28
Konum: Konya

Re: Program Bir Kere Çalışsın Çalışıyorsa Onu Aktif Yapsın

Mesaj gönderen Nick_ »

Sn Battosai
Hocam sorunum su kullanıcı programı 1. defa calıstırdı ve program kendını tray a attı. kullanıcı masaustundekı kısayola 2. defa tıklayınca daha once acılmıs olan (system tray dakı) projemı gostertmek ıstıyorum. Application.Restore komutu calısan uygulamada calısacak bı kod. ben sendmessage gıbı bı komutla oncekı acılan uygulamaya bısıler gondertmem gerekıyor sanırım ama buladım.
Bilmemek ayıp değil öğrenmek isteyene öğretmemek ayıp:)
Kullanıcı avatarı
sabanakman
Kıdemli Üye
Mesajlar: 3077
Kayıt: 17 Nis 2006 08:11
Konum: Ah bi Antalya olaydı keşke (Ankara)

Re: Program Bir Kere Çalışsın Çalışıyorsa Onu Aktif Yapsın

Mesaj gönderen sabanakman »

Bununla ilgili küçük bir örnek eklesem iyi olacak. İşlerimin yoğun olmadığı bir ara (mesela bu akşam :) ) gerekli eklemeyi yapar makaleyi on göre tamamlarım.
Şaban Şahin AKMAN
_________________
Derin olan kuyu değil kısa olan iptir. - .
Kullanıcı avatarı
Nick_
Üye
Mesajlar: 122
Kayıt: 01 Eki 2007 09:28
Konum: Konya

Re: Program Bir Kere Çalışsın Çalışıyorsa Onu Aktif Yapsın

Mesaj gönderen Nick_ »

sabanakman yazdı:Bununla ilgili küçük bir örnek eklesem iyi olacak. İşlerimin yoğun olmadığı bir ara (mesela bu akşam :) ) gerekli eklemeyi yapar makaleyi on göre tamamlarım.
Sağolun hocam bekliyoruz..
Bilmemek ayıp değil öğrenmek isteyene öğretmemek ayıp:)
norths
Üye
Mesajlar: 9
Kayıt: 07 Tem 2009 09:23

Re: Program Bir Kere Çalışsın Çalışıyorsa Onu Aktif Yapsın

Mesaj gönderen norths »

Merhaba Arkadaslar epeyce bi arandiktan sonra hazir biseyler bulamayacagimi farkedip kollari sivadim
biraz tarhana corbasi biraz araklamaci gazeteci mantigi oldu ama calisiyor umarim isinize yarar :))))

kolay gelsin... kodlarini yuruttugum kestigim bictigim ve ekledigim arkadaslardanda ozur dilerim :)))
Bs..

Kod: Tümünü seç

program Project1;

uses
  Forms,
  Windows,
  Unit1 in 'Unit1.pas' {Form1};
{$R *.res}
const AeFrmCptn='Bs_Deneme_001';
var Hndl001,Hndl002:THandle;
begin
   Hndl001:=FindWindow(PChar(String(TForm1.ClassName)),AeFrmCptn);
   if Hndl001=0 then
                  begin
                     Application.Initialize;
                     Application.CreateForm(TForm1, Form1);
                     Form1.Caption:=AeFrmCptn;
                     Application.Run;
                  end
                else
                  begin
                     Hndl002:=getwindow(Hndl001,GW_OWNER);
                     ShowWindow(Hndl002,SW_RESTORE);
                     SetForegroundWindow(Hndl002);
                  end;
end.
Okann
Üye
Mesajlar: 81
Kayıt: 09 Tem 2010 02:55

Re: Program Bir Kere Çalışsın Çalışıyorsa Onu Aktif Yapsın

Mesaj gönderen Okann »

bu şekilde yine çalışmıyor. program içersinden hide komutu ile programı gizlediğimizde exeden yeniden çalıştırmak istediğimiz zaman programın başlığı taskbara geliyor fakat programın kendisi açılamıyor.
Ekim
Üye
Mesajlar: 5
Kayıt: 23 Kas 2019 12:28

Re: Program Bir Kere Çalışsın Çalışıyorsa Onu Aktif Yapsın

Mesaj gönderen Ekim »

sabanakman yazdı: 05 Haz 2007 09:15 Herkese iyi çalışmalar;

Aslında bu konu formda defalarca ifade edildi ve bir arama yapıldığı zaman onlarca cevap bulunacaktır. Burada konu ile ilgili son bir toparlama bilgi vermek için bu yazıyı yazmak istedim.

Genelde bir program çalışıyorsa 2. defa çalışmasını engellemek için en sık karşılaşılan yöntem Mutex oluşturmak ve bunu kullanmak olacaktır. Progamımızın .dpr dosyasına (<-.dpr açıklaması için not eklendi):

Kod: Tümünü seç

// uses Windows, SysUtils, Dialogs
var hMyMutex : tHandle;
begin
  hMyMutex := CreateMutex(nil,FALSE,'Deneme');
  if (hMyMutex <> 0) then try
    if (GetLastError <> ERROR_ALREADY_EXISTS) then begin
      Application.Initialize;
      Application.CreateForm(TForm1,Form1);
      Application.Run;
    end else ShowMessage ('Program zaten çalışıyor');
  finally
    CloseHandle (hMyMutex);
  end else ShowMessage ('Program tanım oluşturmada hata : ' + IntToStr(GetLastError));
end.
kodunu yazdığımız zaman bu işlem gerçekleşmektedir. Peki ama çalışan programı ekranda aktif hale getirmek istiyorsak ne yapmalıyız. Bu daha çok sistem saatinin yanında simge halinde bekleyen (system try) programlar için yaygındır. Diyelimki gelişmiş bir saat programı yazıldı ve progamı 1'den fazla açmak pek mantıklı durmuyor. Ama 2., 3. defa çalıştırılmaya kalkışıldığında orada çalışır halde bekleyen programı aktif yapmak istiyorsak o zaman farklı bir metot kullanmak gerekiyor. FindWindow(ClassName,Caption) API fonksiyonu işimizi görecektir. Bu fonksiyon başlığını (Caption) verdiğimiz programın Handle numarasını verecektir. Hatta sınıf ismini de (ClassName) kullanarak daha isabetli bir arama yapılabilir. Çünkü bir windows oturumunda bir çok program penceresi çalıştırılmaktadır ve bu pencere başlıkları tesadüfen aynı değere sahip olabilir. Bir arama sonucunda istenmeyen başka bir program bulunduğunda ise bizim programımız açılmayacaktır. Bu durumu ortadan kaldırmak için daha açıklayıcı Caption değeri verilmesi yeterli olsa da ClassName'i de işin içine katmanın daha şık olacağı kanaatindeyim. Mesela yazdığımız programın Caption değeri Saat ve sınıf adı da TFormSaat ise bu programı FindWindow(nil,'Saat') fonksiyonuyla testpit edebileceğimiz gibi FindWindow('TFormSaat','Saat') fonksiyonuyla da bulabiliriz ve 2. yöntem bizi daha doğru sonuca götürecektir. Delphi dilinin bir güzel özelliği de oluşturulan sınıfları Windows için aynı sınıf isminde oluşturmasıdır. Bir nesnenin Windows sınıf ismini

Kod: Tümünü seç

function WinClassName(const Handle:THandle):String;
var Buffer: array[0..MAX_PATH] of Char;
begin
  Windows.GetClassName(Handle,Buffer,MAX_PATH);
  Result:=Buffer;
end;
fonksiyonuyla öğrenebiliriz. Mesela ShowMessage(WinClassName(FormSaat.Handle)); kodu ile ekrana TFormSaat mesajı gelecektir. Şimdi bu bilgiler doğrultusunda çalışan programı aktif hale getirelim. Yine .dpr dosyamızda kod yazacağız.

Kod: Tümünü seç

// uses Windows, SysUtils, Dialogs
const SaatCaption='Saat';
var ProgHwnd:THandle; 
begin
  ProgHwnd:=FindWindow(PChar(String(TFormSaat.ClassName)),SaatCaption);
  {ProgHwnd:=FindWindow(nil,SaatCaption); {<-bu da iş görür ancak Caption çakışmasını engellemek gerek :) }
  if ProgHwnd=0 then begin
    Application.Initialize;
    Application.CreateForm(TFormSaat, FormSaat);
    FormSaat.Caption:=SaatCaption;
{FormSaat formu tasarım anında başlığı boş olmalıdır, yoksa delphi ekranı açıkken sorun oluşabilir. ProgHwnd:=FindWindow... kodu delphi tasarımında olan formu bularak istenmeyen bir durum oluşturabilir.}
    Application.Run;
  end else begin
    SetForegroundWindow(ProgHwnd); //<-Öne getir
  end;
end.
Böylelikle çalışır durumda bulunan proje varsa bu aktif hale gelecek, yoksa da o zaman program normal çalışmasına devam edecektir. Herkese çalışmalarında başarılar dilerim.

------------------------------------------------------------------------------------------
Not:Projede çalışılan formların oluşturulduğu

Kod: Tümünü seç

program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.
benzeri kodlara sahip bir proje dosyası bulunmaktadır. Bu dosya projenin ana dosyasıdır ve Project->View Source menü seçeneği ile ulaşılabilinir.
Peki bunu C++ Builder nasil yapabiliriz.... bu yonde bilgilendirme imkani varsa paylasirmisin... Simdiden tesekkurler...
Cevapla