writing a metro like window for our applications with delphi

22
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 Writinga Metrolikewindowfor our applications withDelphi 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

Upload: itamar-monteiro

Post on 18-Feb-2018

226 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 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

Page 2: 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 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$ ;

Page 3: 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 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$ ;

 

Page 4: 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 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.

Page 5: 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 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

Page 6: 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 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$

Page 7: 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 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$$;

Page 8: 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 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;

Page 9: 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 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.

Page 10: 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 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#$;

Page 11: 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 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

Page 12: 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 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

Page 13: 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 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.

Page 14: 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 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;

Page 15: 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 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

Page 16: 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 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.

Page 17: 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 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

Page 18: 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 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.

Page 19: 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 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-

Page 20: 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 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

Page 21: 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 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.

Page 22: 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 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