1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
|
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Menus, ExtCtrls;
{$B-}
type
TfrSpeMenu = class(TForm)
Label1: TLabel;
gbFen: TGroupBox;
butDelDef_fr: TButton;
butDelPers_fr: TButton;
butMkPers_fr: TButton;
gbApplication: TGroupBox;
butMkPers_app: TButton;
butDelDef_app: TButton;
butDelPers_app: TButton;
PnKillExe: TPanel;
procedure FormCreate(Sender: TObject);
procedure butDelDef_frClick(Sender: TObject);
procedure butDelPers_frClick(Sender: TObject);
procedure butMkPers_frClick(Sender: TObject);
procedure butDelDef_appClick(Sender: TObject);
procedure butMkPers_appClick(Sender: TObject);
procedure butDelPers_appClick(Sender: TObject);
procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure PnKillExeClick(Sender: TObject);
private
procedure PopProceeder(var Msg:TMessage); //message WM_SYSCOMMAND;
protected
procedure OnMessageApplicationParser(var Msg:TMsg; var Handled:Boolean);
published
procedure ShowAbout;
procedure ShowPerf;
procedure ICheckBox;
procedure MalinRate;
procedure InfoMode;
end;
TSubmenuItemBox = record
Flag, //type de bouton
ID, //identificateur unique mais dont la valeur arbitraire
Extent: cardinal; //code de correspondance entre les fenêtres
Action: procedure of object; //procédure associée, toujours initialisée à NIL
Caption: string; //libellé
end;
var frSpeMenu : TfrSpeMenu;
SysCheck : boolean = false;
SwMenusExe : boolean = false; //dit si les menus persos au niveau de la barre de tâches sont affichés
const
MN_BASE = $0F; //arbitraire
MN_ALL = MN_BASE + 1; //l'item apparaît partout
MN_Application = MN_BASE + 2; //l'item apparaît en bas de l'écran
MN_frSpeMenu = MN_BASE + 3; //l'item apparaît seulement dans la fenêtre
MaxSubItemCount = 10; //MaxSubItemCount+1 items en vrac classés dans un tableau
//La position relative des cases du tableau sont corrélées
//à celle finale dans le menu. ATTENTION!! cela génère des
//décalages d'indice si vous déplacer une case.
var
SubsItems : array[0..MaxSubItemCount] of TSubmenuItemBox = (
//J'ai choisi des identificateurs (ID) arbitraire.
//Démarre à 800 pour les séparateurs, à 1024 pour les items
( Flag:MF_SEPARATOR; ID:801; Extent:MN_frSpeMenu; Action: nil; Caption:''),
( Flag:MF_STRING; ID:1025; Extent:MN_frSpeMenu; Action: nil; Caption:'&A propos'+#9+'Ctrl+F1'), //pour comment insérer un ShortCut
( Flag:MF_STRING; ID:1026; Extent:MN_frSpeMenu; Action: nil; Caption:'&Performances'),
( Flag:MF_STRING; ID:SC_TASKLIST; Extent:MN_Application; Action: nil; Caption:'&Menu démarrer'), //évènement automatiquement de Windows
( Flag:MF_SEPARATOR; ID:802; Extent:MN_Application; Action: nil; Caption:''),
( Flag:MF_STRING or MF_UNCHECKED; ID:1027; Extent:MN_Application; Action: nil; Caption:'&Case à cocher'),
( Flag:MF_STRING or MF_DISABLED; ID:1028; Extent:MN_Application; Action: nil; Caption:'Cliques ici un peu pour voir... hein ?'),
( Flag:MF_SEPARATOR; ID:803; Extent:MN_frSpeMenu; Action: nil; Caption:''),
( Flag:MF_STRING; ID:SC_MONITORPOWER; Extent:MN_frSpeMenu; Action: nil; Caption:'ATTENTION: Moniteur en veille'),
( Flag:MF_STRING; ID:1029; Extent:MN_frSpeMenu; Action: nil; Caption:'Informations sur le mode ci-dessus'),
( Flag:MF_STRING or MF_DISABLED or MF_GRAYED;
ID:1030; Extent:MN_frSpeMenu; Action: nil; Caption:'Inactif')
//Faîtes gaffe à l'évènement OnCreate si vous bougez des lignes
);
//Merci de laisser les ID uniques les uns par rapport aux autres...
implementation
{$R *.DFM}
//================================================= GESTIONNAIRE
var SysMen : integer; //variable pour la récupération de handles
SwMenusPrs : boolean = false; //dit si les menus persos sont affichés
//Cette variable doit être interne à Unit1. C'est pour cela qu'elle est ici.
procedure TfrSpeMenu.OnMessageApplicationParser(var Msg:TMsg; var Handled:Boolean);
var M : TMessage;
begin
if Msg.message=WM_SYSCOMMAND then
begin
M.WParamLo:=Msg.wParam; //Seul wParamLo est géré
frSpeMenu.PopProceeder(M);
end
else inherited;
end;
procedure KillSystemMenu(Hwd:integer);
begin
//Les nombres suivants tapent dans les ID = 60 000, et déclarés dans WINDOWS.PAS
SysMen:=GetSystemMenu(Hwd,false);
DeleteMenu(SysMen, SC_MAXIMIZE, MF_BYCOMMAND);
DeleteMenu(SysMen, SC_MINIMIZE, MF_BYCOMMAND);
DeleteMenu(SysMen, SC_SIZE, MF_BYCOMMAND);
DeleteMenu(SysMen, SC_RESTORE, MF_BYCOMMAND);
DeleteMenu(SysMen, SC_MOVE, MF_BYCOMMAND);
end;
procedure NoClosePossible(Hwd:integer);
begin
SysMen:=GetSystemMenu(Hwd,false);
DeleteMenu(SysMen, SC_CLOSE, MF_BYCOMMAND);
end;
procedure MkInnerItems(Hwd,Extension:integer);
var i : integer;
begin
SysMen:=GetSystemMenu(Hwd,false);
for i:=0 to MaxSubItemCount do
if (SubsItems[i].Extent=Extension) or (SubsItems[i].Extent=MN_ALL) then
AppendMenu(SysMen, SubsItems[i].Flag, SubsItems[i].ID, PChar(SubsItems[i].Caption));
end;
procedure KillInnerItems(Hwd,Extension:integer);
var i : integer;
begin
SysMen:=GetSystemMenu(Hwd,false);
for i:=0 to MaxSubItemCount do
if (SubsItems[i].Extent=Extension) or (SubsItems[i].Extent=MN_ALL) then
DeleteMenu(SysMen, SubsItems[i].ID, MF_BYCOMMAND);
end;
procedure TfrSpeMenu.PopProceeder(var Msg:TMessage);
var i : integer;
begin
inherited;
for i:=0 to MaxSubItemCount do
if SubsItems[i].ID=Msg.WParamLo then
begin
if Assigned(SubsItems[i].Action) then
SubsItems[i].Action; //On lance l'évènement associé à l'item
Break;
end;
end;
function ChangeMenuState(Hwd, Flag, Ident: integer):boolean;
begin
ChangeMenuState:=ModifyMenu(
GetSystemMenu(Hwd,false), //on prend le menu de l'Application
SubsItems[Ident].ID, //on précise l'identificateur (d'où l'utilité qu'il soit unique
MF_BYCOMMAND or Flag, //un flag de style, couplé à un paramétreur de paramètre de position (euh?)
SubsItems[Ident].ID, //on garde le même ID
PChar(SubsItems[Ident].Caption) //texte
);
end;
function ChangeMenuCheckState(Hwd:integer; Value:boolean; Ident:integer):boolean;
const CheckingTbl : array[boolean] of integer = (MF_UNCHECKED, MF_CHECKED);
var Flag : integer;
begin
Flag:=(SubsItems[Ident].Flag) and (not MF_CHECKED) and (not MF_UNCHECKED);
Flag:=Flag or CheckingTbl[Value];
ChangeMenuCheckState:=ChangeMenuState(Hwd, Flag, Ident);
end;
function SetMenuEnabledState(Hwd:integer; Value:boolean; Ident:integer):boolean;
const EnablingTbl : array[boolean] of integer = (MF_ENABLED, MF_DISABLED);
var Flag : integer;
begin
Flag:=(SubsItems[Ident].Flag) and (not MF_DISABLED) and (not MF_ENABLED);
Flag:=Flag or EnablingTbl[Value];
SetMenuEnabledState:=ChangeMenuState(Hwd, Flag, Ident);
end;
function GetMenuStyle(Hwd:integer; Ident:integer):TMenuItemInfo;
var MnItms : TMenuItemInfo;
begin
GetMenuItemInfo( GetSystemMenu(Hwd,false),
Ident, false, //on sélectionne par l'ID
MnItms ); //retour des résultats
GetMenuStyle:=MnItms;
end;
function HasMenuStyle(Style, Key : integer):boolean;
begin
HasMenuStyle:= (Style and (not Key))=Key; //que de la logique ;) !!
end;
//================================================= INTERFACE VISUELLE DE L'APPLICATION
procedure TfrSpeMenu.FormCreate(Sender: TObject);
begin
Application.OnMessage:=OnMessageApplicationParser;
//ATTRIBUTION DES EVENEMENTS
SubsItems[1].Action:=ShowAbout;
SubsItems[2].Action:=ShowPerf;
SubsItems[5].Action:=ICheckBox;
SubsItems[6].Action:=MalinRate;
SubsItems[9].Action:=InfoMode;
end;
procedure TfrSpeMenu.butDelDef_frClick(Sender: TObject);
begin
KillSystemMenu(frSpeMenu.Handle);
end;
procedure TfrSpeMenu.butDelPers_frClick(Sender: TObject);
begin
KillInnerItems(frSpeMenu.Handle,MN_frSpeMenu);
SwMenusPrs:=false;
end;
procedure TfrSpeMenu.butMkPers_frClick(Sender: TObject);
begin
MkInnerItems(frSpeMenu.Handle, MN_frSpeMenu);
SwMenusPrs:=true;
end;
procedure TfrSpeMenu.butMkPers_appClick(Sender: TObject);
begin
MkInnerItems(Application.Handle, MN_Application);
SwMenusExe:=true;
end;
procedure TfrSpeMenu.butDelPers_appClick(Sender: TObject);
begin
KillInnerItems(Application.Handle,MN_Application);
SwMenusExe:=false;
end;
procedure TfrSpeMenu.butDelDef_appClick(Sender: TObject);
begin
SysCheck:=false; //si nouvelle création, alors non coché par défaut
KillSystemMenu(Application.Handle);
end;
//================================================= EVENEMENTS LOGICIEL
procedure TfrSpeMenu.ShowAbout;
begin
ShowMessage('Tu sais pas lire ? ;)');
end;
procedure TfrSpeMenu.ShowPerf;
begin
ShowMessage('Ce programme est plutôt très très intéressant.');
end;
procedure TfrSpeMenu.ICheckBox;
begin
SysCheck:=not SysCheck;
if ChangeMenuCheckState(Application.Handle,SysCheck,5) then
begin
SetMenuEnabledState(Application.Handle, not SysCheck, 6);
ShowMessage('Vous pouvez peut-être cliquer maintenant là où vous ne pouviez pas tout à l''heure...');
end;
end;
procedure TfrSpeMenu.MalinRate;
begin
NoClosePossible(Application.Handle);
NoClosePossible(frSpeMenu.Handle);
PnKillExe.Caption:='Cliques ici pour quitter...';
PnKillExe.Font.Style:=[fsBold];
ShowMessage('T''as triché en cochant la case à cocher... pff !!'+#13#10#13#10+
'Pour la peine, je t''interdis définitivement de fermer l''application. Au moins une bonne '+
'raison pour comment faire des boîtes de dialogue non closables avec la croix.'+#13#10#13#10+
'Mais comme je suis sympa, je t''active un beau bouton pour partir quand même 8=)');
end;
procedure TfrSpeMenu.InfoMode;
begin
ShowMessage('Si vous mettez en veille et appuyez sur ESPACE alors que le bouton "Créer perso" est focusé, '+
'alors Windows considére l''ESPACE comme commande de fin de veille, mais aussi comme clic équivalent '+
'sur le bouton. Ainsi, des items ont été rajoutés. Utiliser de préférence la touche ECHAP pour fermer.');
end;
procedure TfrSpeMenu.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
//EXEMPLE DE GESTION DES SHORTCUT PERSONELS DANS LES MENUS
if ((Key=VK_F1) and (Shift = [ssCtrl])) and
(SwMenusPrs) and //l'évaluation est couperet
(Assigned(SubsItems[1].Action)) then
SubsItems[1].Action;
end;
procedure TfrSpeMenu.PnKillExeClick(Sender: TObject);
begin
if Copy(PnKillExe.Caption,1,1)<>'J' then
begin
ShowMessage('Ce fut une belle démo... non ?');
Application.Terminate;
end;
end;
end. |
Partager