henryreynolds
asked on
Closing AND HANDLING WINDOWS Multiple Open Delphi exe AND HANDLING WINDOWS
Hi TheRealLoki
You help me with opening multiple exe and closing them. The reason why I opening this question again is as follows.
I have a EXE that acts as a Main Menu, the main menu call differnet delphi exe from the main form , depend on the user selection. PLEASE NOTE my main
menu form IS MY MENU APPLICATION, that's its only purpose to act as a MAIN MENU..
NOW I have a desktop ICON on the client computers that points to the main menu e.g c:\ABC\MainMenu.exe.
Once the user clicks on the Shortcut it will open the Main Menu. If a user click on a menu item, it will create a new process and a new window will show .....
This mean their will be currently two windows open.. (TheRealLoki help me to opening new windows and it work 100% and Also closing them work 100%).
NOW MY NEW QUESTION IS AS FOLLOWS:::
If the user open a menu item and the new window show, then I want this windows to act as a child form of the main menu, or vice versa. What I want to accomplish is the following. If the user minimize the main form or any other window created from my main menu it must minimize ALL the windows,
OR IF THE USER CLICK ON THE SAME MENU ITEM CREATED PREVIOUSLY IT MUST MAXIMIZED THAT WINDOW. I want to limit the user of handling this windows created by my application, because currently now, if he opens a menu item from the main menu that already exists it just make a beep and it does not maximize that window. here is my code what I try to accomplish from my main menu..
procedure TfrmMain.FormCreate(Sender : TObject);
begin
prgName := ExtractFileName(Applicatio n.ExeName) ;
//Check if other instance exist
hMutex := CreateMutex(nil, False, pchar(prgName));
foundApp := not (WaitForSingleObject(hMute x, 0) <> wait_TimeOut);
if foundApplication then
begin
instHdl := StrToInt(strHwnd);
setForegroundWindow(hMutex );
PostMessage(Application.Ha ndle, WM_QUIT, 0, 0);
exit;
end;
To make this question as simple as possible. I want the following.
If My main menu are already running, and the user click on the desktop shortcut IT must not create the window again, IT MUST MAXIMIZE THE CURRENT MAIN MENU AND SET IT AS THE FOCUS WINDOW ON THE DESKTOP.. the same for menu items if the menu item are already opened, and the user have ALT-TAB back to the main menu and try to open the same menu item, it must maximized that open window.
AND FOR A BONUS IF IT IS POSSIBLE, if the user minimize one of my windows it must minimize all the windows, the reason for this IS SOMETIMES will the user is busy with my application a client phones and the client reuest a document from word, NOW the user must go and minimize all my application windows ONE BY ONE, and that is quite BAD..
THANK YOU for trying to help me
HENRY
You help me with opening multiple exe and closing them. The reason why I opening this question again is as follows.
I have a EXE that acts as a Main Menu, the main menu call differnet delphi exe from the main form , depend on the user selection. PLEASE NOTE my main
menu form IS MY MENU APPLICATION, that's its only purpose to act as a MAIN MENU..
NOW I have a desktop ICON on the client computers that points to the main menu e.g c:\ABC\MainMenu.exe.
Once the user clicks on the Shortcut it will open the Main Menu. If a user click on a menu item, it will create a new process and a new window will show .....
This mean their will be currently two windows open.. (TheRealLoki help me to opening new windows and it work 100% and Also closing them work 100%).
NOW MY NEW QUESTION IS AS FOLLOWS:::
If the user open a menu item and the new window show, then I want this windows to act as a child form of the main menu, or vice versa. What I want to accomplish is the following. If the user minimize the main form or any other window created from my main menu it must minimize ALL the windows,
OR IF THE USER CLICK ON THE SAME MENU ITEM CREATED PREVIOUSLY IT MUST MAXIMIZED THAT WINDOW. I want to limit the user of handling this windows created by my application, because currently now, if he opens a menu item from the main menu that already exists it just make a beep and it does not maximize that window. here is my code what I try to accomplish from my main menu..
procedure TfrmMain.FormCreate(Sender
begin
prgName := ExtractFileName(Applicatio
//Check if other instance exist
hMutex := CreateMutex(nil, False, pchar(prgName));
foundApp := not (WaitForSingleObject(hMute
if foundApplication then
begin
instHdl := StrToInt(strHwnd);
setForegroundWindow(hMutex
PostMessage(Application.Ha
exit;
end;
To make this question as simple as possible. I want the following.
If My main menu are already running, and the user click on the desktop shortcut IT must not create the window again, IT MUST MAXIMIZE THE CURRENT MAIN MENU AND SET IT AS THE FOCUS WINDOW ON THE DESKTOP.. the same for menu items if the menu item are already opened, and the user have ALT-TAB back to the main menu and try to open the same menu item, it must maximized that open window.
AND FOR A BONUS IF IT IS POSSIBLE, if the user minimize one of my windows it must minimize all the windows, the reason for this IS SOMETIMES will the user is busy with my application a client phones and the client reuest a document from word, NOW the user must go and minimize all my application windows ONE BY ONE, and that is quite BAD..
THANK YOU for trying to help me
HENRY
ASKER
Hi yes I am a single developer, I did all the applications.
Let me explain why I did all the single exe and One Main Form.
My customer have many small brances in south africa, some branches need a lot of changes to current applications like Capturing Of Sales transactions, for me to create ONE BIG DELPHI application with about 60 forms WAS a NO,NO, because of maintaining such big application.
Then I thought about creating small modules (exe) for each type of Transaction or report or enquiry, this mean each branch has it own set of exe's.
This makes my LIFE a lot easier, because now if a other branch ask me for a sales report and IF branch "D" have maybe that report already I just modify that exe and copy the exe to that branch. This way I can easily keep version control. The other reason why I aslo did it, because some branches doesnt want a other branches to have the same LOOK AND FEEL of a same application, now each branch has it own look of feel of applications like using a mouse, or keybord or have a blue or black background..........
***********
MY APPLICATIONS INHERITS A MAIN FORM AND A DATAMODULE. This mean each time a create a new app. I inherit my main form and a datamodule. This way I only call certain functions once.
*** Each new application will then consist of the following forms..
Main Form (INHERIT FORM)
NewForm (This is the form where a place my button , grids etc.. on, it inherit from Main Form)
Datamode(Inherit)
Dm (new Datamodule that are inherited from Datamodule)
The reason why I explain this, maybe it will give you a idea how my applications works.
My Main Menu Application is the same it inherit from my Main Form and Datamodule.
Thanx I hope you have a idea.
(The only thing i want to accomlpish now is, to make this WHOLE APPLICATION to ACT AS ONE APPLICATION, because the closing of forms is 100% I just want the user to feel more incontrol, AND I dont want the user to go and minimize one by one applications that where open by my main menu, AND if he click on the shortcut on the desktop again, then the main menu must resize again and set focus)
Thank you
HEnRy
Let me explain why I did all the single exe and One Main Form.
My customer have many small brances in south africa, some branches need a lot of changes to current applications like Capturing Of Sales transactions, for me to create ONE BIG DELPHI application with about 60 forms WAS a NO,NO, because of maintaining such big application.
Then I thought about creating small modules (exe) for each type of Transaction or report or enquiry, this mean each branch has it own set of exe's.
This makes my LIFE a lot easier, because now if a other branch ask me for a sales report and IF branch "D" have maybe that report already I just modify that exe and copy the exe to that branch. This way I can easily keep version control. The other reason why I aslo did it, because some branches doesnt want a other branches to have the same LOOK AND FEEL of a same application, now each branch has it own look of feel of applications like using a mouse, or keybord or have a blue or black background..........
***********
MY APPLICATIONS INHERITS A MAIN FORM AND A DATAMODULE. This mean each time a create a new app. I inherit my main form and a datamodule. This way I only call certain functions once.
*** Each new application will then consist of the following forms..
Main Form (INHERIT FORM)
NewForm (This is the form where a place my button , grids etc.. on, it inherit from Main Form)
Datamode(Inherit)
Dm (new Datamodule that are inherited from Datamodule)
The reason why I explain this, maybe it will give you a idea how my applications works.
My Main Menu Application is the same it inherit from my Main Form and Datamodule.
Thanx I hope you have a idea.
(The only thing i want to accomlpish now is, to make this WHOLE APPLICATION to ACT AS ONE APPLICATION, because the closing of forms is 100% I just want the user to feel more incontrol, AND I dont want the user to go and minimize one by one applications that where open by my main menu, AND if he click on the shortcut on the desktop again, then the main menu must resize again and set focus)
Thank you
HEnRy
ok, well to have your application only run once, and restore, change your .DPR to look similar to this
(Alt-View_Project Source)
var
PrevFMain : hwnd; {handle variable}
begin
Application.Initialize;
PrevFMain := FindWindow('TFMain', 'Payroll Program- Main Form');
{Hyphens required(type mismatch if not used.) First }
{parameter is the class, second is the CAPTION }
{that is used for your Main Form, NOT the name }
{of the form.}
if PrevFMain <> 0 then
begin
ShowWindow(PrevFMain, sw_restore); {Activates and displays the window, if minimized or maximized, at}
{it's original size and position}
SetForegroundWindow(PrevFM ain); {Brings it to the front}
Application.Terminate;
end;
Application.CreateForm(TFM ain, FMain); // otherwise, if this is the only instance, create the form and show it as normally
Application.Run;
end.
(Alt-View_Project Source)
var
PrevFMain : hwnd; {handle variable}
begin
Application.Initialize;
PrevFMain := FindWindow('TFMain', 'Payroll Program- Main Form');
{Hyphens required(type mismatch if not used.) First }
{parameter is the class, second is the CAPTION }
{that is used for your Main Form, NOT the name }
{of the form.}
if PrevFMain <> 0 then
begin
ShowWindow(PrevFMain, sw_restore); {Activates and displays the window, if minimized or maximized, at}
{it's original size and position}
SetForegroundWindow(PrevFM
Application.Terminate;
end;
Application.CreateForm(TFM
Application.Run;
end.
Ok, I think this does everything you asked for
*** The Main "Menu" Applicaiton ***
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;
type
TMyProcessObject = class
public
MsgMenuExec, ProgName, RunPath, Exename: string;
ProcessID: cardinal;
StillRunning: boolean;
constructor Create(MsgMenuExec_, ProgName_, RunPath_, Exename_: string; ProcessID_: cardinal);
end;
type
TfrmMain = class(TForm)
bStartNotepad: TButton;
bStartCalc: TButton;
Timer1: TTimer;
bStartProject2: TButton;
bStartProject3: TButton;
Label1: TLabel;
bRestoreAll: TButton;
procedure bStartNotepadClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure bStartCalcClick(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure bStartProject2Click(Sender : TObject);
procedure bStartProject3Click(Sender : TObject);
procedure bRestoreAllClick(Sender: TObject);
private
{ Private declarations }
function SpawnOrRestoreProcess(MsgM enuExec_, ProgName_, RunPath_, Exename_: string): boolean;
function SpawnProcess(MsgMenuExec_, ProgName_, RunPath_, Exename_: string): boolean;
procedure Message_FromClientProgram( var msg: TMessage); message WM_USER+100;
public
{ Public declarations }
MyProcessList: TList;
end;
var
frmMain: TfrmMain;
implementation
{$R *.DFM}
//This function finds the windows and closes them
function EnumWindowsProcClose(Handl e: THandle; List: TList): boolean; stdcall;
var
i: integer;
found: boolean;
wndPid: THandle;
begin
Result := True;
found := false;
i := 0;
GetWindowThreadProcessId(H andle, @wndPid);
while (not found) and (i < List.Count) do
begin
if (wndPid = TMyProcessObject(List[i]). ProcessID) then
begin
found := true;
PostMessage(Handle, WM_Close, 0, 0);
// or PostMessage(Handle, WM_CancelMode, 0, 0); first in case it has a dialog, or wm_quit, etc..
end
else inc(i);
end;
end;
//This function finds the windows and sets the StillRunning flag
function EnumWindowsProcCheckRunnin g(Handle: THandle; List: TList): boolean; stdcall;
var
i: integer;
found: boolean;
wndPid: THandle;
begin
Result := True;
found := false;
i := 0;
GetWindowThreadProcessId(H andle, @wndPid);
while (not found) and (i < List.Count) do
begin
if (wndPid = TMyProcessObject(List[i]). ProcessID) then
begin
found := true;
TMyProcessObject(List[i]). StillRunni ng := True;
end
else inc(i);
end;
end;
//This function finds the windows and minimizes them
function EnumWindowsProcMinimize(Ha ndle: THandle; List: TList): boolean; stdcall;
var
i: integer;
found: boolean;
wndPid: THandle;
begin
Result := True;
found := false;
i := 0;
GetWindowThreadProcessId(H andle, @wndPid);
while (not found) and (i < List.Count) do
begin
if (wndPid = TMyProcessObject(List[i]). ProcessID) then
begin
found := true;
SendMessage( Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0 );
end
else inc(i);
end;
end;
//This function finds the windows and restores them
function EnumWindowsProcRestore(Han dle: THandle; List: TList): boolean; stdcall;
var
i: integer;
found: boolean;
wndPid: THandle;
begin
Result := True;
found := false;
i := 0;
GetWindowThreadProcessId(H andle, @wndPid);
while (not found) and (i < List.Count) do
begin
if (wndPid = TMyProcessObject(List[i]). ProcessID) then
begin
found := true;
SendMessage( Handle, WM_SYSCOMMAND, SC_RESTORE, 0 );
end
else inc(i);
end;
end;
//This function restores and brings to front a specific process
function EnumWindowsProcRestoreAndB ringToFron tSpecificP rocess(Han dle: THandle; ProcessID_: THandle): boolean; stdcall;
var
found: boolean;
wndPid: THandle;
begin
Result := True;
GetWindowThreadProcessId(H andle, @wndPid);
if (wndPid = ProcessID_) then
begin
SendMessage( Handle, WM_SYSCOMMAND, SC_RESTORE, 0 );
SetForegroundWindow(Handle );
end;
end;
procedure TfrmMain.bStartProject2Cli ck(Sender: TObject);
begin
SpawnOrRestoreProcess('Msg MenuExec', 'Project2', ExtractFilePath(Paramstr(0 )), 'project2.exe');
end;
procedure TfrmMain.bStartProject3Cli ck(Sender: TObject);
begin
SpawnOrRestoreProcess('Msg MenuExec', 'Project3', ExtractFilePath(Paramstr(0 )), 'project3.exe');
end;
procedure TfrmMain.bStartNotepadClic k(Sender: TObject);
begin
SpawnOrRestoreProcess('Msg MenuExec', 'Notepad', 'c:\windows\', 'notepad.exe');
end;
procedure TfrmMain.bStartCalcClick(S ender: TObject);
begin
SpawnOrRestoreProcess('Msg MenuExec', 'Calc', 'c:\windown\system32\', 'calc.exe');
end;
procedure TfrmMain.bRestoreAllClick( Sender: TObject);
begin
EnumWindows(@EnumWindowsPr ocRestore, integer(MyProcessList));
Application.Restore;
Application.BringToFront;
end;
function TfrmMain.SpawnOrRestorePro cess(MsgMe nuExec_, ProgName_, RunPath_, Exename_: string): boolean;
var
i: integer;
foundat: integer;
begin
result := false;
i := 0;
foundat := -1;
while (foundat = -1) and (i < MyProcessList.Count) do
begin
if (
(TMyProcessObject(MyProces sList[i]). MsgMenuExe c = MsgMenuExec_) and
(TMyProcessObject(MyProces sList[i]). ProgName = ProgName_)
) then foundat := i else inc(i);
end;
if foundat = -1 then result := SpawnProcess(MsgMenuExec_, ProgName_, RunPath_, Exename_)
else
begin // already running this so find it, restore it, and bring it to the front
EnumWindows(@EnumWindowsPr ocRestoreA ndBringToF rontSpecif icProcess,
integer(TMyProcessObject(M yProcessLi st[foundat ]).Process ID));
result := true;
end;
end;
function TfrmMain.SpawnProcess(MsgM enuExec_, ProgName_, RunPath_, Exename_: string): boolean;
var
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
begin
result := false;
Timer1.Enabled := False;
try
fillChar( startupInfo, sizeof( startupInfo ), 0 );
StartupInfo.cb := sizeof( startupInfo );
StartupInfo.wShowWindow := SW_SHOW;
if (CreateProcess(nil, PChar(RunPath_ + ExeName_), nil, nil, False,
NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo)) then
begin
MyProcessList.Add(TMyProce ssObject.C reate(MsgM enuExec_, ProgName_, RunPath_,
Exename_,ProcessInfo.dwPro cessId));
result := true;
end
else
MessageDlg(MsgMenuExec_ + #13 + '(' + ProgName_ + ')', mtWarning, [mbOK], 0)
finally
Timer1.Enabled := True;
end;
end;
procedure TfrmMain.FormCreate(Sender : TObject);
begin
MyProcessList := TList.Create;
Timer1.Enabled := True;
Caption := 'Main Menu';
end;
procedure TfrmMain.FormDestroy(Sende r: TObject);
begin
MyProcessList.Clear;
MyProcessList.Free;
end;
procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Timer1.Enabled := False;
EnumWindows(@EnumWindowsPr ocClose, integer(MyProcessList));
end;
procedure TfrmMain.Message_FromClien tProgram(v ar msg: TMessage);
begin
if msg.WParam = 1 then
begin // minimize all related windows, including this one
EnumWindows(@EnumWindowsPr ocMinimize , integer(MyProcessList));
Application.Minimize;
end;
end;
procedure TfrmMain.Timer1Timer(Sende r: TObject);
var
i: integer;
begin
Timer1.Enabled := False;
try
for i:= 0 to pred(MyProcessList.Count) do
TMyProcessObject(MyProcess List[i]).S tillRunnin g := False;
// this next part marks any processes as "StillRunning"
EnumWindows(@EnumWindowsPr ocCheckRun ning, integer(MyProcessList));
for i:= pred(MyProcessList.Count) downto 0 do
begin
if not TMyProcessObject(MyProcess List[i]).S tillRunnin g then
begin // this process is no longer running, re-enable the button for it
if (
(TMyProcessObject(MyProces sList[i]). MsgMenuExe c = 'MsgMenuExec') and
(TMyProcessObject(MyProces sList[i]). ProgName = 'Notepad')
) then bStartNotepad.Enabled := True
else if (
(TMyProcessObject(MyProces sList[i]). MsgMenuExe c = 'MsgMenuExec') and
(TMyProcessObject(MyProces sList[i]). ProgName = 'Calc')
) then bStartCalc.Enabled := True
else if (
(TMyProcessObject(MyProces sList[i]). MsgMenuExe c = 'MsgMenuExec') and
(TMyProcessObject(MyProces sList[i]). ProgName = 'Project2')
) then bStartProject2.Enabled := True
else if (
(TMyProcessObject(MyProces sList[i]). MsgMenuExe c = 'MsgMenuExec') and
(TMyProcessObject(MyProces sList[i]). ProgName = 'Project3')
) then bStartProject3.Enabled := True;
// Delete this process from our list since it is no longer running
MyProcessList.Delete(i);
end;
end;
finally
Timer1.Enabled := True;
end;
end;
{ TMyProcessObject }
constructor TMyProcessObject.Create(Ms gMenuExec_ , ProgName_, RunPath_, Exename_: string; ProcessID_: cardinal);
begin
inherited Create;
MsgMenuExec := MsgMenuExec_;
ProgName := ProgName_;
RunPath := RunPath_;
Exename := Exename_;
ProcessID := ProcessID_;
end;
end.
******** FORM FOLLOWS *********
object frmMain: TfrmMain
Left = 367
Top = 247
Width = 255
Height = 290
Caption = 'frmMain'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
OnClose = FormClose
OnCreate = FormCreate
OnDestroy = FormDestroy
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 24
Top = 96
Width = 200
Height = 33
AutoSize = False
Caption =
'The following 2 do not minimize and restore because we did not w' +
'rite them'
WordWrap = True
end
object bStartNotepad: TButton
Left = 72
Top = 136
Width = 91
Height = 25
Caption = 'bStartNotepad'
TabOrder = 2
OnClick = bStartNotepadClick
end
object bStartCalc: TButton
Left = 72
Top = 168
Width = 91
Height = 25
Caption = 'bStartCalc'
TabOrder = 3
OnClick = bStartCalcClick
end
object bStartProject2: TButton
Left = 72
Top = 16
Width = 89
Height = 25
Caption = 'bStartProject2'
TabOrder = 0
OnClick = bStartProject2Click
end
object bStartProject3: TButton
Left = 72
Top = 56
Width = 89
Height = 25
Caption = 'bStartProject3'
TabOrder = 1
OnClick = bStartProject3Click
end
object bRestoreAll: TButton
Left = 72
Top = 216
Width = 91
Height = 25
Caption = 'bRestoreAll'
TabOrder = 4
OnClick = bRestoreAllClick
end
object Timer1: TTimer
Enabled = False
OnTimer = Timer1Timer
Left = 192
Top = 32
end
end
**** NOW YOU NEED TO ADD THIS TO EACH "CLIENT" APPLICATION ***
I'd put this in your "base" unit/form
drop a TApplicationEvents component (from the additional tab) on to the mainform of your other projects
set it's OnMinimize event
ApplicationEvents1: TApplicationEvents;
procedure TForm2.ApplicationEvents1M inimize(Se nder: TObject);
var
mainmenuapp: HWnd;
begin
mainmenuapp := FindWindow('TfrmMain', 'Main Menu');
if mainmenuapp <> 0 then
PostMessage(mainmenuapp, WM_USER+100, 1, 0); // 1 means "Minimize" to the main menu
end;
*** The Main "Menu" Applicaiton ***
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;
type
TMyProcessObject = class
public
MsgMenuExec, ProgName, RunPath, Exename: string;
ProcessID: cardinal;
StillRunning: boolean;
constructor Create(MsgMenuExec_, ProgName_, RunPath_, Exename_: string; ProcessID_: cardinal);
end;
type
TfrmMain = class(TForm)
bStartNotepad: TButton;
bStartCalc: TButton;
Timer1: TTimer;
bStartProject2: TButton;
bStartProject3: TButton;
Label1: TLabel;
bRestoreAll: TButton;
procedure bStartNotepadClick(Sender:
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure bStartCalcClick(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure bStartProject2Click(Sender
procedure bStartProject3Click(Sender
procedure bRestoreAllClick(Sender: TObject);
private
{ Private declarations }
function SpawnOrRestoreProcess(MsgM
function SpawnProcess(MsgMenuExec_,
procedure Message_FromClientProgram(
public
{ Public declarations }
MyProcessList: TList;
end;
var
frmMain: TfrmMain;
implementation
{$R *.DFM}
//This function finds the windows and closes them
function EnumWindowsProcClose(Handl
var
i: integer;
found: boolean;
wndPid: THandle;
begin
Result := True;
found := false;
i := 0;
GetWindowThreadProcessId(H
while (not found) and (i < List.Count) do
begin
if (wndPid = TMyProcessObject(List[i]).
begin
found := true;
PostMessage(Handle, WM_Close, 0, 0);
// or PostMessage(Handle, WM_CancelMode, 0, 0); first in case it has a dialog, or wm_quit, etc..
end
else inc(i);
end;
end;
//This function finds the windows and sets the StillRunning flag
function EnumWindowsProcCheckRunnin
var
i: integer;
found: boolean;
wndPid: THandle;
begin
Result := True;
found := false;
i := 0;
GetWindowThreadProcessId(H
while (not found) and (i < List.Count) do
begin
if (wndPid = TMyProcessObject(List[i]).
begin
found := true;
TMyProcessObject(List[i]).
end
else inc(i);
end;
end;
//This function finds the windows and minimizes them
function EnumWindowsProcMinimize(Ha
var
i: integer;
found: boolean;
wndPid: THandle;
begin
Result := True;
found := false;
i := 0;
GetWindowThreadProcessId(H
while (not found) and (i < List.Count) do
begin
if (wndPid = TMyProcessObject(List[i]).
begin
found := true;
SendMessage( Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0 );
end
else inc(i);
end;
end;
//This function finds the windows and restores them
function EnumWindowsProcRestore(Han
var
i: integer;
found: boolean;
wndPid: THandle;
begin
Result := True;
found := false;
i := 0;
GetWindowThreadProcessId(H
while (not found) and (i < List.Count) do
begin
if (wndPid = TMyProcessObject(List[i]).
begin
found := true;
SendMessage( Handle, WM_SYSCOMMAND, SC_RESTORE, 0 );
end
else inc(i);
end;
end;
//This function restores and brings to front a specific process
function EnumWindowsProcRestoreAndB
var
found: boolean;
wndPid: THandle;
begin
Result := True;
GetWindowThreadProcessId(H
if (wndPid = ProcessID_) then
begin
SendMessage( Handle, WM_SYSCOMMAND, SC_RESTORE, 0 );
SetForegroundWindow(Handle
end;
end;
procedure TfrmMain.bStartProject2Cli
begin
SpawnOrRestoreProcess('Msg
end;
procedure TfrmMain.bStartProject3Cli
begin
SpawnOrRestoreProcess('Msg
end;
procedure TfrmMain.bStartNotepadClic
begin
SpawnOrRestoreProcess('Msg
end;
procedure TfrmMain.bStartCalcClick(S
begin
SpawnOrRestoreProcess('Msg
end;
procedure TfrmMain.bRestoreAllClick(
begin
EnumWindows(@EnumWindowsPr
Application.Restore;
Application.BringToFront;
end;
function TfrmMain.SpawnOrRestorePro
var
i: integer;
foundat: integer;
begin
result := false;
i := 0;
foundat := -1;
while (foundat = -1) and (i < MyProcessList.Count) do
begin
if (
(TMyProcessObject(MyProces
(TMyProcessObject(MyProces
) then foundat := i else inc(i);
end;
if foundat = -1 then result := SpawnProcess(MsgMenuExec_,
else
begin // already running this so find it, restore it, and bring it to the front
EnumWindows(@EnumWindowsPr
integer(TMyProcessObject(M
result := true;
end;
end;
function TfrmMain.SpawnProcess(MsgM
var
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
begin
result := false;
Timer1.Enabled := False;
try
fillChar( startupInfo, sizeof( startupInfo ), 0 );
StartupInfo.cb := sizeof( startupInfo );
StartupInfo.wShowWindow := SW_SHOW;
if (CreateProcess(nil, PChar(RunPath_ + ExeName_), nil, nil, False,
NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo)) then
begin
MyProcessList.Add(TMyProce
Exename_,ProcessInfo.dwPro
result := true;
end
else
MessageDlg(MsgMenuExec_ + #13 + '(' + ProgName_ + ')', mtWarning, [mbOK], 0)
finally
Timer1.Enabled := True;
end;
end;
procedure TfrmMain.FormCreate(Sender
begin
MyProcessList := TList.Create;
Timer1.Enabled := True;
Caption := 'Main Menu';
end;
procedure TfrmMain.FormDestroy(Sende
begin
MyProcessList.Clear;
MyProcessList.Free;
end;
procedure TfrmMain.FormClose(Sender:
begin
Timer1.Enabled := False;
EnumWindows(@EnumWindowsPr
end;
procedure TfrmMain.Message_FromClien
begin
if msg.WParam = 1 then
begin // minimize all related windows, including this one
EnumWindows(@EnumWindowsPr
Application.Minimize;
end;
end;
procedure TfrmMain.Timer1Timer(Sende
var
i: integer;
begin
Timer1.Enabled := False;
try
for i:= 0 to pred(MyProcessList.Count) do
TMyProcessObject(MyProcess
// this next part marks any processes as "StillRunning"
EnumWindows(@EnumWindowsPr
for i:= pred(MyProcessList.Count) downto 0 do
begin
if not TMyProcessObject(MyProcess
begin // this process is no longer running, re-enable the button for it
if (
(TMyProcessObject(MyProces
(TMyProcessObject(MyProces
) then bStartNotepad.Enabled := True
else if (
(TMyProcessObject(MyProces
(TMyProcessObject(MyProces
) then bStartCalc.Enabled := True
else if (
(TMyProcessObject(MyProces
(TMyProcessObject(MyProces
) then bStartProject2.Enabled := True
else if (
(TMyProcessObject(MyProces
(TMyProcessObject(MyProces
) then bStartProject3.Enabled := True;
// Delete this process from our list since it is no longer running
MyProcessList.Delete(i);
end;
end;
finally
Timer1.Enabled := True;
end;
end;
{ TMyProcessObject }
constructor TMyProcessObject.Create(Ms
begin
inherited Create;
MsgMenuExec := MsgMenuExec_;
ProgName := ProgName_;
RunPath := RunPath_;
Exename := Exename_;
ProcessID := ProcessID_;
end;
end.
******** FORM FOLLOWS *********
object frmMain: TfrmMain
Left = 367
Top = 247
Width = 255
Height = 290
Caption = 'frmMain'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
OnClose = FormClose
OnCreate = FormCreate
OnDestroy = FormDestroy
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 24
Top = 96
Width = 200
Height = 33
AutoSize = False
Caption =
'The following 2 do not minimize and restore because we did not w' +
'rite them'
WordWrap = True
end
object bStartNotepad: TButton
Left = 72
Top = 136
Width = 91
Height = 25
Caption = 'bStartNotepad'
TabOrder = 2
OnClick = bStartNotepadClick
end
object bStartCalc: TButton
Left = 72
Top = 168
Width = 91
Height = 25
Caption = 'bStartCalc'
TabOrder = 3
OnClick = bStartCalcClick
end
object bStartProject2: TButton
Left = 72
Top = 16
Width = 89
Height = 25
Caption = 'bStartProject2'
TabOrder = 0
OnClick = bStartProject2Click
end
object bStartProject3: TButton
Left = 72
Top = 56
Width = 89
Height = 25
Caption = 'bStartProject3'
TabOrder = 1
OnClick = bStartProject3Click
end
object bRestoreAll: TButton
Left = 72
Top = 216
Width = 91
Height = 25
Caption = 'bRestoreAll'
TabOrder = 4
OnClick = bRestoreAllClick
end
object Timer1: TTimer
Enabled = False
OnTimer = Timer1Timer
Left = 192
Top = 32
end
end
**** NOW YOU NEED TO ADD THIS TO EACH "CLIENT" APPLICATION ***
I'd put this in your "base" unit/form
drop a TApplicationEvents component (from the additional tab) on to the mainform of your other projects
set it's OnMinimize event
ApplicationEvents1: TApplicationEvents;
procedure TForm2.ApplicationEvents1M
var
mainmenuapp: HWnd;
begin
mainmenuapp := FindWindow('TfrmMain', 'Main Menu');
if mainmenuapp <> 0 then
PostMessage(mainmenuapp, WM_USER+100, 1, 0); // 1 means "Minimize" to the main menu
end;
ASKER
Morning TheRealLoki
Hi just started working now, I will do what you said and let you know through the course of the day.
Thank you again for your GREAT help
Henry
South Africa
Hi just started working now, I will do what you said and let you know through the course of the day.
Thank you again for your GREAT help
Henry
South Africa
ASKER
Hi TheRealLoki
I have started with the .dpr PART.
I am not sure if i am correct. I took my Main Menu application and change the dpr of my main menu application is this CORRECT ??
This Is my code
Application.Initialize;
PrevFMain := FindWindow('TfrmMainMenu', 'MainMenu' );
{Hyphens required(type mismatch if not used.) First }
{parameter is the class, second is the CAPTION }
{that is used for your Main Form, NOT the name }
{of the form.}
if PrevFMain <> 0 then
begin
ShowWindow(PrevFMain, sw_restore); {Activates and displays the window, if minimized or maximized, at}
{it's original size and position}
SetForegroundWindow(PrevFM ain); {Brings it to the front}
Application.Terminate;
end;
PerformPackageUpdate;
Application.CreateForm(Tfr mMainMenu, frmMainMenu);
Application.Run;
*** But when a debug and comes to the line PrevFMain FindWindow, it founded already a instance.. If i go and create a new application from scratch then IT WORKS.
I dont know if it is to do with my inheritance, because I inherited from a Form Call Main Form, and in the Main form on its oncreate event I intiliazie my
datamodule.. Here is a example.
procedure TfrmMain.FormCreate(Sender : TObject);
begin
if dm = nil then dm := Tdm.Create(Application); //intiliaze Datamodule to create a login screen and load Default Database values
dm.IBDatabase.Connected := False;
if not dm.Login then
begin
MessageDlg('Login failed.', mtWarning, [mbOk], 0);
PostMessage(Application.Ha ndle, WM_QUIT, 0, 0);
exit;
end;
if not dm.IBDatabase.Connected then
begin
MessageDlg('Error connecting to database', mtError, [mbOk], 0);
Application.Terminate;
exit;
end;
end;
Can it be something on my inheritance, because there are currently nowhere my Main Menu application are running.
I have started with the .dpr PART.
I am not sure if i am correct. I took my Main Menu application and change the dpr of my main menu application is this CORRECT ??
This Is my code
Application.Initialize;
PrevFMain := FindWindow('TfrmMainMenu',
{Hyphens required(type mismatch if not used.) First }
{parameter is the class, second is the CAPTION }
{that is used for your Main Form, NOT the name }
{of the form.}
if PrevFMain <> 0 then
begin
ShowWindow(PrevFMain, sw_restore); {Activates and displays the window, if minimized or maximized, at}
{it's original size and position}
SetForegroundWindow(PrevFM
Application.Terminate;
end;
PerformPackageUpdate;
Application.CreateForm(Tfr
Application.Run;
*** But when a debug and comes to the line PrevFMain FindWindow, it founded already a instance.. If i go and create a new application from scratch then IT WORKS.
I dont know if it is to do with my inheritance, because I inherited from a Form Call Main Form, and in the Main form on its oncreate event I intiliazie my
datamodule.. Here is a example.
procedure TfrmMain.FormCreate(Sender
begin
if dm = nil then dm := Tdm.Create(Application); //intiliaze Datamodule to create a login screen and load Default Database values
dm.IBDatabase.Connected := False;
if not dm.Login then
begin
MessageDlg('Login failed.', mtWarning, [mbOk], 0);
PostMessage(Application.Ha
exit;
end;
if not dm.IBDatabase.Connected then
begin
MessageDlg('Error connecting to database', mtError, [mbOk], 0);
Application.Terminate;
exit;
end;
end;
Can it be something on my inheritance, because there are currently nowhere my Main Menu application are running.
ASKER
Hi TheRealLoki
I have go on to the minimize part now......Still cant get first part right
Before I changed my Main menu I have first tested the new minimizing on a new project.
1) When I run it and call project 2,3 (a single form with a label on) from the app IT work 100%.
BUT when I replace project2 with a exe created with the inheritance and login screen (my normal client applications) it calls correctly..
but when I minimize the client application, then on my taskbar and on top of it, its creating small rectangle blocks about 50 of them, and also when I minimize it seems as it does it twice (maybe it does it twice because it does it for the Normal form and once for the Inherited form)...
I really dont undertsand why it go's so weird.
And also when I click on my main menu again to call that module again then it acts weird, it brings the previoused created form to the front BUT it also creating a white rectangle block in my left corner of my screen.
I must have a probem with all the single individual modules(the Main and Inherited Form) .
Sorry I give you a lot of problems, but you are the only one who understand my problem.
Thank you
Henry
I have go on to the minimize part now......Still cant get first part right
Before I changed my Main menu I have first tested the new minimizing on a new project.
1) When I run it and call project 2,3 (a single form with a label on) from the app IT work 100%.
BUT when I replace project2 with a exe created with the inheritance and login screen (my normal client applications) it calls correctly..
but when I minimize the client application, then on my taskbar and on top of it, its creating small rectangle blocks about 50 of them, and also when I minimize it seems as it does it twice (maybe it does it twice because it does it for the Normal form and once for the Inherited form)...
I really dont undertsand why it go's so weird.
And also when I click on my main menu again to call that module again then it acts weird, it brings the previoused created form to the front BUT it also creating a white rectangle block in my left corner of my screen.
I must have a probem with all the single individual modules(the Main and Inherited Form) .
Sorry I give you a lot of problems, but you are the only one who understand my problem.
Thank you
Henry
ASKER
Hi TheRealLoki
I have take a client application and remove the
if dm = nil then dm := Tdm.Create(Application); //intiliaze Datamodule to create a login screen and load Default Database values
from the Main Form, then it seems to work when I minimize the form. I dont know why the datamodule would make the screen go so funny.
Let me just refresh how I DID all the client application.
-In Delphi6 I created a new application.
-Then i removed Unit1 from the appication.
-The I go and Add to my project the Datamodule.pas and MainForm.Pas {These are the forms that will be Inherited, by the newly created forms.The Datamodule load database values and loads the login screen. The MainForm just do a resize and has some default buttons on it and some default functions like GetEmployee Details}
-Then I go and say File->New->Other->project- >And select formMain as inherit, and Datamodule as inherit.
-Now I have a new Unit1, and Unit2.
-I rename Unit1 to the project name for the application like (frmMonthlySalesRep)
-I rename my Unit2 to dm
-I rename the project to prjMonthlySalesRep
This mean I have a frmMonthlySales where I place extra components on and do all my coding for this project. If I need to inherit some function I inherit from my MainForm, or inherit from my Datamodule
*****MY MainForm***********{My main form is just a .pas file it is not a project}
{I use paramaters to send to my datamodule, the paramaters are a username,password and a databasename
My MainMenu also get these paramaters from my Datamodule, I save thsese paramaters in local varaibles}
On my MainForm onCreate event I call the following
if dm = nil then dm := Tdm.Create(Application); //intiliaze Datamodule to create a login screen and load Default Database values
dm.IBDatabase.Connected := False;
if not dm.Login then //in my datamodule I call a function login this function check if there are a username and passowrd and a database send as paramaters
begin
MessageDlg('Login failed.', mtWarning, [mbOk], 0);
PostMessage(Application.Ha ndle, WM_QUIT, 0, 0);
exit;
end;
if not dm.IBDatabase.Connected then
begin
MessageDlg('Error connecting to database', mtError, [mbOk], 0);
Application.Terminate;
exit;
end;
****************Somehwere here I must have a mistake*******************
I thought i just explain to you again to let you know how my mind work.
Thanx Henry
I have take a client application and remove the
if dm = nil then dm := Tdm.Create(Application); //intiliaze Datamodule to create a login screen and load Default Database values
from the Main Form, then it seems to work when I minimize the form. I dont know why the datamodule would make the screen go so funny.
Let me just refresh how I DID all the client application.
-In Delphi6 I created a new application.
-Then i removed Unit1 from the appication.
-The I go and Add to my project the Datamodule.pas and MainForm.Pas {These are the forms that will be Inherited, by the newly created forms.The Datamodule load database values and loads the login screen. The MainForm just do a resize and has some default buttons on it and some default functions like GetEmployee Details}
-Then I go and say File->New->Other->project-
-Now I have a new Unit1, and Unit2.
-I rename Unit1 to the project name for the application like (frmMonthlySalesRep)
-I rename my Unit2 to dm
-I rename the project to prjMonthlySalesRep
This mean I have a frmMonthlySales where I place extra components on and do all my coding for this project. If I need to inherit some function I inherit from my MainForm, or inherit from my Datamodule
*****MY MainForm***********{My main form is just a .pas file it is not a project}
{I use paramaters to send to my datamodule, the paramaters are a username,password and a databasename
My MainMenu also get these paramaters from my Datamodule, I save thsese paramaters in local varaibles}
On my MainForm onCreate event I call the following
if dm = nil then dm := Tdm.Create(Application); //intiliaze Datamodule to create a login screen and load Default Database values
dm.IBDatabase.Connected := False;
if not dm.Login then //in my datamodule I call a function login this function check if there are a username and passowrd and a database send as paramaters
begin
MessageDlg('Login failed.', mtWarning, [mbOk], 0);
PostMessage(Application.Ha
exit;
end;
if not dm.IBDatabase.Connected then
begin
MessageDlg('Error connecting to database', mtError, [mbOk], 0);
Application.Terminate;
exit;
end;
****************Somehwere here I must have a mistake*******************
I thought i just explain to you again to let you know how my mind work.
Thanx Henry
the main .DPR part may get confused and find the window in delphi
To stop this, set your main form's caption to "blah" in delphi
but in the main form's create set it to what you really want
(see my formcreate() above)
eg. caption := 'main menu';
To stop this, set your main form's caption to "blah" in delphi
but in the main form's create set it to what you really want
(see my formcreate() above)
eg. caption := 'main menu';
ASKER
Morning
Sorry have change the on create event of my main menu form to create the caption on the oncreate event. Now is works 100% it, only creates my main menu once. The only thing is, when i minimize the main menu and run the main menu again , then it maximixed. BUT you cant minimize the window again.
-> Now for all my single exe (modules) I have also change the the caption to the on create event. But when I still call this exe from my main menu application ,
It creates it fine, BUT when i minimize it it still makes rectangle blocks on the bottom of my desktop (small blue rectangle blocks) AND if I go
and click on the button to say run project 2 again (the exe that are cuurently minimized) if restore the windows BUT while it is restoring you can see on my desktop on the left how small windows are popuping up( it's like small windows popuping up from the bottom of my desktop) after that the windows will restore to normal.
As I said previously, I think its my Datamodule that makes this funny events of the windows, because if i take the datamodule out, then it works 100%
Thank you Henry
Sorry have change the on create event of my main menu form to create the caption on the oncreate event. Now is works 100% it, only creates my main menu once. The only thing is, when i minimize the main menu and run the main menu again , then it maximixed. BUT you cant minimize the window again.
-> Now for all my single exe (modules) I have also change the the caption to the on create event. But when I still call this exe from my main menu application ,
It creates it fine, BUT when i minimize it it still makes rectangle blocks on the bottom of my desktop (small blue rectangle blocks) AND if I go
and click on the button to say run project 2 again (the exe that are cuurently minimized) if restore the windows BUT while it is restoring you can see on my desktop on the left how small windows are popuping up( it's like small windows popuping up from the bottom of my desktop) after that the windows will restore to normal.
As I said previously, I think its my Datamodule that makes this funny events of the windows, because if i take the datamodule out, then it works 100%
Thank you Henry
I think it is minimizing to a box on screen because your datamodule is the "main form" so to speak, instead of the form..
You need the application to minimize rather than just the form minimize I guess.
I'll look into it later, but you could try messing with the .dpr, or specifically set "Application.MainForm := Form1;
You need the application to minimize rather than just the form minimize I guess.
I'll look into it later, but you could try messing with the .dpr, or specifically set "Application.MainForm := Form1;
ASKER
Thank you, I agree i think it minimize the datamodule also, because sometimes when activate the application again from the main menu it makes a white rectangle screen in the left of the windows(quite a big white window)
Thank you again for helping me, I APPRECIATE ITE A LOT
HENRY
Thank you again for helping me, I APPRECIATE ITE A LOT
HENRY
ah yes, the "can't minimize" problem
that happens because you need an application.restore, the "showwindow" does not do enough
sorry.
change your main .DPR code to this
if PrevFMain <> 0 then
begin
ShowWindow(PrevFMain, sw_restore); {Activates and displays the window, if minimized or maximized, at}
{it's original size and position}
SetForegroundWindow(PrevFM ain); {Brings it to the front}
PostMessage(PrevFMain, wm_user + 100, 2, 0); // 2 means do a restore please
Application.Terminate;
end;
and change your main form procedure to this
procedure TfrmMain.Message_FromClien tProgram(v ar msg: TMessage);
begin
if msg.WParam = 1 then
begin // minimize all related windows, including this one
EnumWindows(@EnumWindowsPr ocMinimize , integer(MyProcessList));
Application.Minimize;
end
else if msg.WParam = 2 then
begin // restore this application
Application.Restore;
end;
end;
that happens because you need an application.restore, the "showwindow" does not do enough
sorry.
change your main .DPR code to this
if PrevFMain <> 0 then
begin
ShowWindow(PrevFMain, sw_restore); {Activates and displays the window, if minimized or maximized, at}
{it's original size and position}
SetForegroundWindow(PrevFM
PostMessage(PrevFMain, wm_user + 100, 2, 0); // 2 means do a restore please
Application.Terminate;
end;
and change your main form procedure to this
procedure TfrmMain.Message_FromClien
begin
if msg.WParam = 1 then
begin // minimize all related windows, including this one
EnumWindows(@EnumWindowsPr
Application.Minimize;
end
else if msg.WParam = 2 then
begin // restore this application
Application.Restore;
end;
end;
ASKER
Morning TheRealLoki
How was your weekend? I have change my main menu dpr, its fine now thanx.
I just want to find out if you will still help me of fixing the problem when I minimize a called exe module, because I tried a lof of things this weekend with my datamodule but with no luck. I can undersatnd why it makes such funny windows when you minimize a seperate module (I AM CONFUSED), becayse if I just compile a new project without a datamodule and called that exe then is is 100%.
THANK YOU
HENRY
How was your weekend? I have change my main menu dpr, its fine now thanx.
I just want to find out if you will still help me of fixing the problem when I minimize a called exe module, because I tried a lof of things this weekend with my datamodule but with no luck. I can undersatnd why it makes such funny windows when you minimize a seperate module (I AM CONFUSED), becayse if I just compile a new project without a datamodule and called that exe then is is 100%.
THANK YOU
HENRY
can you paste the .DPR of one of thos e datamodule applications here
I know some code that will work aound it, but maybe we just need to change teh order of things in your dpr
I know some code that will work aound it, but maybe we just need to change teh order of things in your dpr
ASKER
Hi this is a module that performs journal enquiries... I have not change anything yet THIS IS EXACLTY HOW IT IS CURRENTLY
program prjJournalsEnquiry;
uses
Forms,
formMAIN in '..\..\Packages\formMAIN.p as' {frmMain}, //***********INHERIT FORMMAIN
DataModule in '..\..\Packages\DataModule .pas' {dmBase: TDataModule},//*********** INHERIT DATAMODULE
data in 'data.pas' {dm: TDataModule},
formJournalsEnquiry in 'formJournalsEnquiry.pas' {frmJournalsEnquiry},
formReport in 'formReport.pas' {frmReport};
{$R *.res}
begin
Application.Initialize;
Application.Title := 'Journal Document Enquiry';
Application.CreateForm(Tfr mJournalsE nquiry, frmJournalsEnquiry);
Application.Run;
program prjJournalsEnquiry;
uses
Forms,
formMAIN in '..\..\Packages\formMAIN.p
DataModule in '..\..\Packages\DataModule
data in 'data.pas' {dm: TDataModule},
formJournalsEnquiry in 'formJournalsEnquiry.pas' {frmJournalsEnquiry},
formReport in 'formReport.pas' {frmReport};
{$R *.res}
begin
Application.Initialize;
Application.Title := 'Journal Document Enquiry';
Application.CreateForm(Tfr
Application.Run;
ASKER
Hi
Sorry but i am struggeling now for 5 hours with STILL the minimize problem when you restore the main menu. I said previously it work but when I tested i thourogly i saw sometimes the minimize still does not work.
Here is my dpr code for my main menu
program prjMainMenu;
uses
Forms,
Windows,
SysUtils,
Dialogs,
Messages,
formMAIN in '..\..\Packages\formMAIN.p as' {frmMain},
UpdatePackage in 'UpdatePackage.pas',
DataModule in '..\..\Packages\DataModule .pas' {dmBase: TDataModule},
data in 'data.pas' {dm: TDataModule},
formMainMenu in 'formMainMenu.pas' {frmMainMenu};
{$R *.res}
var
PrevFMain : hwnd; {handle variable}
begin
Application.Initialize;
PerformPackageUpdate;
PrevFMain := FindWindow('TfrmMainMenu', 'Bizcom Main Menu');
{Hyphens required(type mismatch if not used.) First }
{parameter is the class, second is the CAPTION }
{that is used for your Main Form, NOT the name }
{of the form.}
if PrevFMain <> 0 then
begin
ShowWindow(PrevFMain, sw_restore); {Activates and displays the window, if minimized or maximized, at}
{it's original size and position}
SetForegroundWindow(PrevFM ain); {Brings it to the front}
PostMessage(PrevFMain, wm_user + 100, 2, 0); // 2 means do a restore please
Application.Terminate;
end;
Application.CreateForm(Tfr mMainMenu, frmMainMenu); // otherwise, if this is the only instance, create the form and show it as normally
Application.Run;
end.
Sorry but i am struggeling now for 5 hours with STILL the minimize problem when you restore the main menu. I said previously it work but when I tested i thourogly i saw sometimes the minimize still does not work.
Here is my dpr code for my main menu
program prjMainMenu;
uses
Forms,
Windows,
SysUtils,
Dialogs,
Messages,
formMAIN in '..\..\Packages\formMAIN.p
UpdatePackage in 'UpdatePackage.pas',
DataModule in '..\..\Packages\DataModule
data in 'data.pas' {dm: TDataModule},
formMainMenu in 'formMainMenu.pas' {frmMainMenu};
{$R *.res}
var
PrevFMain : hwnd; {handle variable}
begin
Application.Initialize;
PerformPackageUpdate;
PrevFMain := FindWindow('TfrmMainMenu',
{Hyphens required(type mismatch if not used.) First }
{parameter is the class, second is the CAPTION }
{that is used for your Main Form, NOT the name }
{of the form.}
if PrevFMain <> 0 then
begin
ShowWindow(PrevFMain, sw_restore); {Activates and displays the window, if minimized or maximized, at}
{it's original size and position}
SetForegroundWindow(PrevFM
PostMessage(PrevFMain, wm_user + 100, 2, 0); // 2 means do a restore please
Application.Terminate;
end;
Application.CreateForm(Tfr
Application.Run;
end.
I've tried making an application like yours, but I'm not getting the problem.
the .DPR creates the main form, and the ain form creates a datamodule.
when you click on the minimize button, youare getting it minimizing to the bottome left of the screen
is this correct?
It's not doing it for me. perhaps I need to try it with inheritence
the .DPR creates the main form, and the ain form creates a datamodule.
when you click on the minimize button, youare getting it minimizing to the bottome left of the screen
is this correct?
It's not doing it for me. perhaps I need to try it with inheritence
ASKER
Morning cant I sent you my forms then maybe it will be much easier for you to solve.
Thanx
Thanx
sure lokiwashere at yahoo dot co dot nz, zip'em up if you can
ASKER
Thank you I have sent the forms right now.
HEnry
HEnry
ah found it
the problem is in my main menu code :-(
the EnumWindows calls see the datamodule as well as the form, so it sends them a minimize, causing it to go to the bottom left.
my code changes below will stop once it sends a minimize to the first window (which should be the main menu) so it works
change the following bits to this code :-
type
TMyProcessObject = class
public
MsgMenuExec, ProgName, RunPath, Exename: string;
ProcessID: cardinal;
StillRunning: boolean;
SentMinimize: boolean;
constructor Create(MsgMenuExec_, ProgName_, RunPath_, Exename_: string; ProcessID_: cardinal);
end;
...
//This function finds the windows and minimizes them
function EnumWindowsProcMinimize(Ha ndle: THandle; List: TList): boolean; stdcall;
var
i: integer;
found: boolean;
wndPid: THandle;
begin
Result := True;
found := false;
i := 0;
GetWindowThreadProcessId(H andle, @wndPid);
while (not found) and (i < List.Count) do
begin
if (wndPid = TMyProcessObject(List[i]). ProcessID) and
(not TMyProcessObject(List[i]). SentMinimi ze) then
begin
found := true;
SendMessage( Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0 );
TMyProcessObject(List[i]). SentMinimi ze := True;
end
else inc(i);
end;
end;
...
procedure TfrmMain.Message_FromClien tProgram(v ar msg: TMessage);
var
i: integer;
begin
if msg.WParam = 1 then
begin // minimize all related windows, including this one
for i := 0 to pred(MyProcessList.Count) do TMyProcessObject(MyProcess List[i]).S entMinimiz e := False;
EnumWindows(@EnumWindowsPr ocMinimize , integer(MyProcessList));
Application.Minimize;
end
else if msg.WParam = 2 then
begin // restore this application
Application.Restore;
end;
end;
the problem is in my main menu code :-(
the EnumWindows calls see the datamodule as well as the form, so it sends them a minimize, causing it to go to the bottom left.
my code changes below will stop once it sends a minimize to the first window (which should be the main menu) so it works
change the following bits to this code :-
type
TMyProcessObject = class
public
MsgMenuExec, ProgName, RunPath, Exename: string;
ProcessID: cardinal;
StillRunning: boolean;
SentMinimize: boolean;
constructor Create(MsgMenuExec_, ProgName_, RunPath_, Exename_: string; ProcessID_: cardinal);
end;
...
//This function finds the windows and minimizes them
function EnumWindowsProcMinimize(Ha
var
i: integer;
found: boolean;
wndPid: THandle;
begin
Result := True;
found := false;
i := 0;
GetWindowThreadProcessId(H
while (not found) and (i < List.Count) do
begin
if (wndPid = TMyProcessObject(List[i]).
(not TMyProcessObject(List[i]).
begin
found := true;
SendMessage( Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0 );
TMyProcessObject(List[i]).
end
else inc(i);
end;
end;
...
procedure TfrmMain.Message_FromClien
var
i: integer;
begin
if msg.WParam = 1 then
begin // minimize all related windows, including this one
for i := 0 to pred(MyProcessList.Count) do TMyProcessObject(MyProcess
EnumWindows(@EnumWindowsPr
Application.Minimize;
end
else if msg.WParam = 2 then
begin // restore this application
Application.Restore;
end;
end;
ASKER
Hi Its almost there, did you see if the window is minimized, and you go and click to reopen that window from the main menu then it makes a with rectangle screen in the left corner when it restores that windows.
Thanx
Thanx
ASKER
Hi did you manage to see the problem when a windows rececive focus again, when you open a previuosed open window from the menu again. I als think it is the datamodule that does the white screen in the left corner.
Thanx
Thanx
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Hi, the probel is when you click on the menu again, AND IF THE WINDOW IS ALREADY opened and it refocus the window, THEN IT make a white window in the left corner. I have sent a screen shot to your yahoo account.
Thanx
Thanx
ASKER
Hi TheRealLoki
Did you maybe managed to see what did the problem is when the windows receive focus again, from the main menu, the screenshot I have sent to your yahoo email account, with the white window in the left corner.
Thank you
Enjoy your weekend
Henry
Did you maybe managed to see what did the problem is when the windows receive focus again, from the main menu, the screenshot I have sent to your yahoo email account, with the white window in the left corner.
Thank you
Enjoy your weekend
Henry
The reason I ask is that if you did, then it gives you more options for the kind of control you want.