Writing a Metro Like Window for Our Applications With Delphi
-
Upload
itamar-monteiro -
Category
Documents
-
view
223 -
download
0
Transcript of Writing a Metro Like Window for Our Applications With Delphi
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 1/22
Writing a Metro like window for our applications with Delphi
Writing a custom Windows UI for a Delphi application.
Bear in mind that I’m not a professional Delphi programmer, it is my hobby and I’m still learning
the tricks behind Windows AI. !o this will be a walkthrough post that will try to achie"e the
following Window #etro like on Windows $ or newer %see image below&.
#aybe the abo"e picture might look too ambicious but as they say, the more difficult the
challenge the better you skills impro"e.
'ope I will get near to it, so let’s start.
Defining the starting point(o begin with, we need to set the window border style as bsnone and we will be building our
#etro)like window taking into consideration e"ery aspect in"ol"ed on its inherent beha"iour, like
resi*ing windows %ma+imi*e, restore, minimi*e, resi*e, mo"e, aero snap, windows hotkeys, and
multimonitor resi*e&.
et’s add a (abel component to use it as a title bar
Align-al(op/ 00It will occupy the top area as normally does the con"entional titlebar Alignment-ta1enter/ 00 it will align the te+t hori*ontally centered
Autosi*e-2alse/ 00 a"oid automatic resi*ing, specially the height
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 2/22
ayout-tl1enter/ 00 it will align the te+t "ertically centered
3ame-lblApp(itle/ 00let’s gi"e it a proper name
(o gi"e it the power to mo"e the window, we will modify the #ouseDown e"ent
procedure TMetroGUI.lblAppTitleMouseMove(Sender: TObject; Shift: TShiftState; !
": Inte#er$;
be#in
%elease&apture;
'erfor()M*S"S&OMMA+,! -/01! /$;
end;
As you can see, we release the mousedown e"ent so no click e"ent will be fired, and we
perform a window system command, the undocumented 42567 that is send to e"ery window
when a Window mo"e e"ent is called.
A gradient color for the background
et’s add a gradient effect to the window, it will gi"e a look like the goal’s background color.
(o achi"e"e that, we will use the code published at
about.delphi.comhttp-00delphi.about.com0od0adptips755809t0gradient:fill.htm
uses Math! ...
procedure Grad2ori3ontal(&anvas:T&anvas; %ect:T%ect; ro&olor! To&olor:T&olor$ ;
var
:inte#er;
dr!d#!db:45tended;
&0!&1:T&olor;
r0!r1!#0!#1!b0!b1:67te;
%!G!6:67te;
cnt:inte#er; be#in
&0 :8 ro&olor;
%0 :8 Get%9alue(&0$ ;
G0 :8 GetG9alue(&0$ ;
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 3/22
60 :8 Get69alue(&0$ ;
&1 :8 To&olor;
%1 :8 Get%9alue(&1$ ;
G1 :8 GetG9alue(&1$ ;
61 :8 Get69alue(&1$ ;
dr :8 (%1%0$ %ect.%i#ht%ect.<eft; d# :8 (G1G0$ %ect.%i#ht%ect.<eft;
db :8 (6160$ %ect.%i#ht%ect.<eft;
cnt :8 /;
for :8 %ect.<eft to %ect.%i#ht0 do
be#in
% :8 %0=&eil(dr>cnt$ ;
G :8 G0=&eil(d#>cnt$ ;
6 :8 60=&eil(db>cnt$ ;
&anvas.'en.&olor :8 %G6(%!G!6$ ; &anvas.MoveTo(!%ect.Top$ ;
&anvas.<ineTo(!%ect.6otto$ ;
inc(cnt$ ;
end;
end;
procedure Grad9ertical(&anvas:T&anvas; %ect:T%ect; ro&olor! To&olor:T&olor$ ;
var
":inte#er;
dr!d#!db:45tended;
&0!&1:T&olor; r0!r1!#0!#1!b0!b1:67te;
%!G!6:67te;
cnt:Inte#er;
be#in
&0 :8 ro&olor;
%0 :8 Get%9alue(&0$ ;
G0 :8 GetG9alue(&0$ ;
60 :8 Get69alue(&0$ ;
&1 :8 To&olor;
%1 :8 Get%9alue(&1$ ; G1 :8 GetG9alue(&1$ ;
61 :8 Get69alue(&1$ ;
dr :8 (%1%0$ %ect.6otto%ect.Top;
d# :8 (G1G0$ %ect.6otto%ect.Top;
db :8 (6160$ %ect.6otto%ect.Top;
cnt :8 /;
for " :8 %ect.Top to %ect.6otto0 do
be#in
% :8 %0=&eil(dr>cnt$ ;
G :8 G0=&eil(d#>cnt$ ;
6 :8 60=&eil(db>cnt$ ;
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 4/22
&anvas.'en.&olor :8 %G6(%!G!6$ ;
&anvas.MoveTo(%ect.<eft!"$ ;
&anvas.<ineTo(%ect.%i#ht!"$ ;
Inc(cnt$ ;
end;
end;
And ;n aint e"ent of the 2orm, we’ll add the following
procedure TMetroGUI.or'aint(Sender: TObject$;
be#in
Grad2ori3ontal(&anvas! &lient%ect! -e?ded@!-e1e@df$;
end;
And the resulting appearance is like this
'owe"er, there is no shadow, and since Windows doesn’t apply the normal shadow to a window
without style, we need to apply by oursel"es, be it by using the so old simple shadow or creating
a layered window as a shadow. (his last one we’ll be a little difficult but doable, let’s <ust start
with the old shadow one.
2or this purpose we need to modify the form create params.
...
protected
procedure &reate'aras(var 'aras: T&reate'aras$;override;
end;
...
ipleentation
...
procedure TMetroGUI.&reate'aras(var 'aras: T&reate'aras$;
be#in
inherited;
'aras.)indo&lass.st7le :8 'aras.)indo&lass.st7le or &S*,%O'S2A,O);
end;
We only need to enable the 1!:D=;!'AD;W flag and we now ha"e a simple shadow.
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 5/22
3ow it ha"e a better look. At the end, I’m planning to add a better shadow using another form.
;n ost 2ocus %onDeacti"e&
3ow let’s add a on lost focus feature, we will change the color of the background to gi"e the
users a hint that our application is not the acti"e one.
et’s create a pri"ate "ariable that will hold the state, and the procedures for acti"ate and
deacti"ate e"ents-
private
B 'rivate declarations C
isocused: 6oolean;
procedure <ostocus(Sender: TObject$;
procedure Setocus(Sender: TObject$;
And they will toggle the focus state an call the repaint procedure
procedure TMetroGUI.<ostocus(Sender: TObject$;
be#in isocused:8alse;
%epaint;
end;
procedure TMetroGUI.Setocus(Sender: TObject$;
be#in
isocused:8True;
%epaint;
end;
But we need to modify the 2ormaint procedure in order to get that effect
procedure TMetroGUI.or'aint(Sender: TObject$;
be#in
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 6/22
if isocused then
Grad2ori3ontal(&anvas! &lient%ect! -e?ded@!-e1e@df$
else
Grad2ori3ontal(&anvas! &lient%ect! -cDc/bD!-c/cEbd$;
end;
3ow, we ha"e to background gradient colors depending on form focus state
(he normal state
and the unfocused state
(he white border line
et’s gi"e it a white line, to gi"e it a different border line
!o, it only needs to be modified the 2ormaint
procedure TMetroGUI.or'aint(Sender: TObject$;
be#in
if isocused then
Grad2ori3ontal(&anvas! &lient%ect! -e?ded@!-e1e@df$
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 7/22
else
Grad2ori3ontal(&anvas! &lient%ect! -cDc/bD!-c/cEbd$;
ith canvas do be#in
'en.&olor:8-eeeeee;
MoveTo(/!/$;
<ineTo(/!&lient2ei#ht0$;
<ineTo(&lient)idth0! &lient2ei#ht0$;
<ineTo(&lient)idth0!/$; <ineTo(/!/$;
end;
end;
We <ust added, with canvas… that draws the almost white line, you can change to any other
color of course
=esi*e borders
It is time to add a resi*e area, generally it will be located in the bottom)right part of the window.
et’s add a simple drawing on the right bottom area of our form adding to our formpaint
procedure
lets dra a resi3e area in the ri#htbotto part 6rush.&olor:8clhite;
ill%ect(rect(&lient)idthF!&lient2ei#htF!&lient)idth1!&lient2ei#ht1$$;
ill%ect(rect(&lient)idth?!&lient2ei#htF!&lient)idth@!&lient2ei#ht1$$;
ill%ect(rect(&lient)idth0/!&lient2ei#htF!&lient)idthD!&lient2ei#ht1$$;
ill%ect(rect(&lient)idth0E!&lient2ei#htF!&lient)idth00!&lient2ei#ht1$$;
ill%ect(rect(&lient)idthF!&lient2ei#ht?!&lient)idth1!&lient2ei#ht@$$;
ill%ect(rect(&lient)idth?!&lient2ei#ht?!&lient)idth@!&lient2ei#ht@$$;
ill%ect(rect(&lient)idth0/!&lient2ei#ht?!&lient)idthD!&lient2ei#ht@$$;
ill%ect(rect(&lient)idthF!&lient2ei#ht0/!&lient)idth1!&lient2ei#htD$$; ill%ect(rect(&lient)idth?!&lient2ei#ht0/!&lient)idth@!&lient2ei#htD$$;
ill%ect(rect(&lient)idthF!&lient2ei#ht0E!&lient)idth1!&lient2ei#ht00$$;
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 8/22
It is a simple way to draw a triangle area with separated dots as shown in the following picture
3ow, it needs to respond a mousedown e"ent that will perform the resi*e action
procedure TMetroGUI.orMouse,on(Sender: TObject; 6utton: TMouse6utton;
Shift: TShiftState; ! ": Inte#er$;
be#in
lets resi3e if on resi3e area
if (H&lient)idth0E$ and (" H &lient2ei#ht00$ then
be#in
%elease&apture;
'erfor()M*S"S&OMMA+,!-//D!/$;
end;
end;
(he form#ouseDown procedure shown abo"e limits the mouse area to that specific area,
sending a system command corresponding to the resi*e width > height together. (he result is-
As you can see, it needs somethign more to make it better, since the painting fails, so we <ust
need to call repaint on resi*e e"ent.
procedure TMetroGUI.or%esi3e(Sender: TObject$;
be#in %epaint;
end;
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 9/22
And that is enough to make it work better.
2i+ing a weird beha"iour on resi*ing the form-
As you can see, the resi*e procedure can resi*e the window too much that the user can turn the
form like a one pi+el form. !o we need to limit the minimum width and height to a"oid that ugly
beha"iour.
!o on 2orm1reate, we define those constraints
procedure TMetroGUI.or&reate(Sender: TObject$;
be#in
Application.On,eactivate:8 <ostocus;
Application.OnActivate:8 Setocus;
&onstraints.Min)idth:8F//;
&onstraints.Min2ei#ht:81//;
end;
3ow we ha"e a better resi*able form.
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 10/22
Double 1lick =esi*e
By now, we ha"e a working e+ample of a form. We need to add a double click e"ent to the
application title bar, so we will add a double click e"ent to the lblApp(itle component.
Adding a double click procedure for the Application (itle
procedure TMetroGUI.lblAppTitle,bl&lic(Sender: TObject$;
be#in
%elease&apture;
if )indoState 8 sMa5ii3ed then
'erfor()M*S"S&OMMA+,!S&*%4STO%4!/$
else
'erfor()M*S"S&OMMA+,!S&*MAIMIJ4!/$;
end;
As you can see, first, we need to know the current window status, if it is already ma+imi*ed,then we will restore it, otherwise, we will ma+imi*e it.
'owe"er, this perform function is okay, but we need to modify something because it will
ma+imi*e to the entire desktop screen si*e without respecting the working area %all window
minus the taskbar area usually&.
As we are sending a syscommand e"ent, we need to modify this e"ent, so let’s add it to the
form pri"ate area
private
B 'rivate declarations C
isocused: 6oolean;
procedure <ostocus(Sender: TObject$;
procedure Setocus(Sender: TObject$;
procedure )MS7s&oand (var Ms#: T)MS7s&oand$; essa#e )M*S"S&OMMA+,;
3ow wee need to handle the ma+imi*e message
procedure TMetroGUI.)MS7s&oand(var Ms#: T)MS7s&oand$;be#in
if Ms#.&dT7pe 8 S&*MAIMIJ4 then
be#in
if ()indoState 8 s+oral$ or ()indoState 8 sMinii3ed$ then
be#in
)indoState:8sMa5ii3ed;
ith Screen.)orArea%ect do
MetroGUI.Set6ounds(<eft! Top! %i#ht <eft 0! 6otto Top 0$;
Ms#.%esult:8/;
45it;
end; end;
,efault2andler(Ms#$;
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 11/22
end;
As you see, we intercept the !1:#A$I#I?@ message and "erify if the current window state is
different than wsMaximized then we change the windowState to wsMaximized and resi*e
according to the screen work area rect %keep in mind this will only work on one monitor setups,
that would be modified later to impro"e it for dual o multimonitor&. Back to the code, we set the
actual form bounds to the si*e of the work area rect, and after that we clear the msg result ande+it before gi"ing the msg to the default window handler.
3ow our form resi*es correctly. In the following steps we will drop that approach with a better
one.
Windows Aero !nap support
What if we like to use the windows hotkeys %winkeyarrowkeys& to resi*e our formC
(his can be done easily since any window that is not borderless %non bs3one&, will respond to
these hotkeys.
(o get that beha"iour, we will add to CreateParams a style for our form,
theWS_OVE!"PPE#W$%#OW
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 12/22
!addly this style gi"es back the non bsnone borderstyle, i.e., it has the non wanted classic
windows border. 'owe"er, this border style responds correctly to WineyArroweys to resi*e
with Aero!nap feature. !o we need to get rid again of this classic windows border style.
protected
procedure )nd'roc(var Messa#e: TMessa#e$;override;
procedure &reate'aras(var 'aras: T&reate'aras$;override;
!o we <ust added a new procedure that will take care of the Windows processes.
procedure TMetroGUI.)nd'roc(var Messa#e: TMessa#e$;
be#in
if Messa#e.Ms# 8 )M*+&&A<&SIJ4 then
be#in
Messa#e.Ms#:8 )M*+U<<;
end;
Inherited )nd'roc(Messa#e$;
end;
(here we will modify the W#:311A1!I?@ message which is used to determine the border
style si*e, and with it the window manager draws the classic border. We change that msg to 5
%W#:3U& as when bsnone borderstyle. And for the other messages, we inherit them.
But, now we see a window resi*e bug when we !nap to the top screen to ma+imi*e it
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 13/22
If you don’t see it, it is the application title bar reduce si*e, if you compare to the pre"ious
snapshot of the ma+imi*e e"ent, you will notice that the title’s caption is located a little bit down.
Before proceeding, we will &et rid o' WMSysCommand proced(re we wrote before, since it is
not needed anymore because we ga"e the almost correct ma+imi*e e"ent with the Aero!nap
feature.
And to fi+ the bad ma+imi*e effect, we will copy the old W#!ys1ommand procedures to
the )ormesizee"ent.
procedure TMetroGUI.or%esi3e(Sender: TObject$;
be#in
if ()indoState 8 sMa5ii3ed$then
be#in
ith Screen.)orArea%ect do
MetroGUI.Set6ounds(<eft! Top! %i#ht <eft0! 6otto Top0$;
end; %epaint;
end;
As in the pre"ious procedure, we need to adapt it for multimonitor setups. We’ll add it later.
We’re good till here. 'owe"er, one thing dri"es to another one. (he new issue due to Win!nap
support is that the old system buttons re appear when we click o"er its area.
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 14/22
(o get rid of it we need to set this application as non layered window.
procedure TMetroGUI.&reate'aras(var 'aras: T&reate'aras$;
be#in
inherited;
'aras.)indo&lass.st7le :8 'aras.)indo&lass.st7le or &S*,%O'S2A,O);
'aras.St7le:8paras.St7le or )S*O94%<A''4,)I+,O) and not )S*S"SM4+U;
end;
!o we <ust added and not WS_S*SME%+ to the arams.!tyle. 'owe"er, there will not be a Alt)!pace application conte+t menu. But in order to gi"e our app the same e+perience as with a
normal form, we can use a tpanel set align to al1lient and the lblApp(itle mo"e inside it, finally
the resi*e mouse area mo"ed to that panel mousedown e"ent.
1lear the (anel bevelo(ter to bv%one and only bypass the mouse down e"ent
procedure TMetroGUI.'anel0Mouse,on(Sender: TObject; 6utton: TMouse6utton;
Shift: TShiftState; ! ": Inte#er$;
be#in
orMouse,on(Sender!6utton! Shift!!"$;end;
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 15/22
@asy, ain’t it, <ust get rid of the anel caption to erase that anel6 string on our form.
#etro like system buttons
3ow, we’re going to add 3E files to mimic the *une metro system menu.
We add them as resource files, with the ro<ect)F=esource and ImagesG menu, if you ha"e a
different Delphi "ersion which lacks that feature, you can still compile =1 files with those files.
;nce done, we can draw them like this.
procedure TMetroGUI.or'aint(Sender: TObject$;var
pn#:T'n#Ia#e;
be#in
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 16/22
...
ith canvas do be#in
...
lets paint the buttons
pn#:8T'n#Ia#e.&reate;
tr7
pn#.<oadro%esource+ae(2Instance!'+G&<OS4$;
,ra(&lient)idth11!D!pn#$; pn#.<oadro%esource+ae(2Instance! '+GMA$;
,ra(&lient)idthFF!D!pn#$;
pn#.<oadro%esource+ae(2Instance! '+GMI+$;
,ra(&lient)idthKK!D!pn#$;
finall7
reeAnd+il(pn#$;
end;
end;
end;
(his has been added to our e+isting 2ormaint procedure. #ake sure to include at Uses clause
the 3EImage unit.
Using (Image for !ysmenu buttons
Instead of drawing our custom system buttons, we will use timages with autosi*e enabled.
=ename them to imgBtn1lose, imgBtn=esi*e, imgBtn#in accordingly.
oad them with the default pictures.
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 17/22
3ow well add their coordinates to the 'ormesize e"ent
...
ali#n our etro s7ste buttons
i#6tn&lose.<eft:8&lient)idth11;
i#6tn&lose.Top:8D;
i#6tn%esi3e.<eft:8&lient)idthFF;
i#6tn%esi3e.Top:8D;
i#6tnMin.<eft:8&lient)idthKK; i#6tnMin.Top:8D;
...
And to interact with mouse o"er and mouse out, we will use the e"ent #ouse@nter and
#ouseea"e
procedure TMetroGUI.i#6tn&loseMouse4nter(Sender: TObject$;
var
pn#: T'n#Ia#e;
be#in
pn# :8 T'n#Ia#e.&reate;
tr7
pn#.<oadro%esource+ae(2Instance! '+G&<OS4O+$;
i#6tn&lose.'icture.Assi#n(pn#$;
finall7
pn#.ree;
end;
end;
procedure TMetroGUI.i#6tn&loseMouse<eave(Sender: TObject$;
var
pn#: T'n#Ia#e;
be#in
pn# :8 T'n#Ia#e.&reate;
tr7
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 18/22
pn#.<oadro%esource+ae(2Instance! '+G&<OS4$;
i#6tn&lose.'icture.Assi#n(pn#$;
finall7
pn#.ree;
end;
end;
And now for the =esi*e button %ma+imi*e > restore&
procedure TMetroGUI.i#6tn%esi3eMouse4nter(Sender: TObject$;
var
pn#: T'n#Ia#e;
be#in
pn# :8 T'n#Ia#e.&reate;
tr7
if )indoState 8 sMa5ii3ed then
pn#.<oadro%esource+ae(2Instance! '+G%4STO%4O+$
else
pn#.<oadro%esource+ae(2Instance! '+GMAO+$;
i#6tn%esi3e.'icture.Assi#n(pn#$;
finall7
pn#.ree;
end;
end;
procedure TMetroGUI.i#6tn%esi3eMouse<eave(Sender: TObject$;
var
pn#: T'n#Ia#e;
be#in
pn# :8 T'n#Ia#e.&reate;
tr7
if )indoState 8 sMa5ii3ed then
pn#.<oadro%esource+ae(2Instance! '+G%4STO%4$
else
pn#.<oadro%esource+ae(2Instance! '+GMA$;
i#6tn%esi3e.'icture.Assi#n(pn#$;
finall7
pn#.ree;
end;
end;
As you can see, first we "erify if our window is ma+imi*ed to either draw the restore icon or the
ma+imi*e one.
3ow, to make sure its icon %button pic& shows the correct one when resi*ing it "ia hotkey or
other ways, we will add to )ormesize this simple procedure call
...
i#6tn%esi3eMouse<eave(Sender$;
...
(hat will be enough to make it aware of resi*ing e"ents and will show the correct button image.
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 19/22
2inally we need to add functions to those custom system buttons.
procedure TMetroGUI.i#6tnMin&lic(Sender: TObject$;
be#in
'erfor()M*S"S&OMMA+,! S&*MI+IMIJ4! /$;
end;
procedure TMetroGUI.i#6tn%esi3e&lic(Sender: TObject$;be#in
if )indoState 8 sMa5ii3ed then
'erfor()M*S"S&OMMA+,! S&*%4STO%4! /$
else
'erfor()M*S"S&OMMA+,! S&*MAIMIJ4!/$;
end;
procedure TMetroGUI.i#6tn&lose&lic(Sender: TObject$;
be#in
close
end;
Always taking into account the window state, specially for the resi*e button.
#ultimonitor !upport
If you ha"e more than one monitor, you will see that it ma+imi*es to only one of them. (o a"oid
that we need to figure it out how many monitors we ha"e, and according to where our
application is, we ma+imi*e to that monitor.
(his is a function that tells us where a specific $,H coordinate is located, i.e., in which monitor.
function )hichMonitor(hori3&enter!vert&enter: inte#er$:inte#er;
var
I: Inte#er;
be#in
result:80;
for I :8 / to Screen.Monitor&ount0 do
be#in
if(screen.MonitorsLI.<eftNhori3&enter$
and(screen.MonitorsLI.<eft=Screen.MonitorsLI.)idthHhori3&enter$
and(Screen.MonitorsLI.TopNvert&enter$
and(Screen.MonitorsLI.Top=Screen.MonitorsLI.2ei#htHvert&enter$
then
result:8I;
end;
end;
!o when resi*ing our form, we make sure that the center $,H of our form is located between
those boundaries.
!o we modify it to include the monitor support-
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 20/22
procedure TMetroGUI.or%esi3e(Sender: TObject$;
be#in
if ()indoState 8 sMa5ii3ed$then
be#in
if Screen.Monitor&ountH0 then
be#in
ith Screen.MonitorsL)hichMonitor(left=idth div 1!top=2ei#ht div
1$.)orarea%ect do MetroGUI.Set6ounds(<eft! Top! %i#ht <eft0! 6otto Top0$;
end
else
ith Screen.)orArea%ect do
MetroGUI.Set6ounds(<eft! Top! %i#ht <eft0! 6otto Top0$;
end;
...
And that’s all, now we ha"e a fully functional #etro !kin.
!H!#@3U by right click on App (itle
;ur application wouldn’t be complete if we lea"e the right click that shows the !ystem #enu of
our application. !o we will use the #ouseUp e"ent of lbl"pp,itle
procedure TMetroGUI.lblAppTitleMouseUp(Sender: TObject; 6utton: TMouse6utton;
Shift: TShiftState; ! ": Inte#er$;
const
)M*S"SM4+U 8 ?D?;
var
': T'oint;
M': Inte#er;be#in
if 6utton 8 b%i#ht then
be#in
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 21/22
':8 &lientToScreen('oint(!"$$;
as
ov a5! ord('."$;
shl ea5! 0K;
ov a5! ord('.$;
ov M'! ea5;
end;
SendMessa#e(2andle!)M*S"SM4+U!/!M'$; end;
end;
2or this purpose we first make sure we clicked with the right button of our mouse %this is hacky
approach since other user might ha"e enabled the left handed feature that uses the oposite
buttons&. Anyways, let’s continue.
(he $ and H "alues store the coordinates relati"e to our form, so we need to con"ert it to screen
coordinates, thankfully with 1lient(o!creen we can do that.
After that we place those new coordinates in a 7bits "alue, the first 68bits holding the H "alue
and the last 68bits the $ "alue. I don’t know how to do it, so assembly might help . And finally
we send a message to our application with the command !ys#@3U and # holding the
coordinates where it will be shown.
1onclusion
#aking a custom Delphi application that mimics the #etro !tyle of ?une is not a tri"ial work
without the knowledge of WI3AI tricks, and taking into consideration e"ery aspect that a
normal application has. 'owe"er, they’re not as difficult as it might look, with the right tools
e"erything is possible. I know there are many ways to achie"e this pseudo skin, with J1
components already built, but I found them the lack of Win!nap, and other features. With this
approach you ha"e the entire control of your code.
7/23/2019 Writing a Metro Like Window for Our Applications With Delphi
http://slidepdf.com/reader/full/writing-a-metro-like-window-for-our-applications-with-delphi 22/22
'owe"er, our work until here is not complete, we need to add a shadow effect and the correct
icons as our main goal was the #etro Browser concept by !putnikK, and of course adding the
WebBrowser support maybe with (WebBrowser or (1hromium.
2inally, I would like to thank you for reading this walkthrough of building a #etro like application
with Delphi. 'ope you liked it and hope it might be of use for your pro<ects. It took me a lot of try
and error, and finally I’"e come up with something I’m satisfied by now.
Download sources
Hou can get this article source codes for free here-
#y final result, "ery ugly, I know.
http://vhanla.codigobit.info/2012/05/writing-custom-window-theme-from.html