Programmer en 'C' sous Windows
MinPrg03: Les contrôles Windows basiques.
Le système fournit un ensemble de fenêtres spécialisées qu'on appèle
"contrôle" et qui permet de fabriquer des interfaces utilisateur graphique (GUI = Graphic User
Interface). Ce sont des boutons, des listes, des boites de saisie etc... L'exemple qui suit montre comment
mettre en oeuvre de tels contrôles.
Les Fichiers |
Organisation du Source Code |
MiniPrg_03.exe (260KB 21-MAR-2008)
MiniPrg_03.zip (83KB 21-MAR-2008)
minprg.h
minprg.c
minprg.rc
tools.h
tools.c
|
|
Que fait ce programme ? : |
On continue d'étoffer notre précédent exemple en ajoutant 4 contrôles Windows
différents : Une boite d'édition (Edit Box), une boite à choix multiples (Combo Box),
un bouton poussoir (Push Button) et un liste à droite (List Box).
Quand on bouge le Slider, chaque modification crée une entrée supplémentaire dans
la liste, la boite de saisie est mise à jour avec la valeur courante du Slider, la combo box est aussi
mise à jour en fonction de la position du Slider.
Quand on saisie une valeur dans l'Edit Box, le Slider et la Combo box sont automatiquement mis à
jour, à chaque nouveau caractère tapé.
La Combo Box permet aussi de changer la valeur du Slider.
La liste Box stock tous les mouvements du Slider et la sélection d'une entrée de la liste
rappelle la position du curseur en mettant à jour les autres contrôles.
un Clic gauche sur le fond de la fenêtre affiche toujours une boite bleu avec l'état des
touches CTRL et SHIFT. Un clic droit déclenche l'ouverture d'un Popup menu.
|
Les grands principes évoqués : |
Les contrôles sont aussi des fenêtres (se créant avec la fonction CreateWindow) mais dont la classe
est déjà définie. On a vu, puisqu'on l'a déjà fait, que la classe d'une
fenêtre est associée à une Callback qui s'occupe de tout son comportement et de ses
fonctionnalités. Dans le cas des contrôles Windows, toute cela est déjà définit par
le système pour les classes dénommées : "edit", "button", "combobox", "listbox" etc...
Ces contrôles sont usuellement des fenêtres filles qui s'affichent dans la partie cliente de la
fenêtre père. L'ordre de leur création donne le Z-Order, c'est à dire l'ordre dans lequel
les fenêtres sont empilées les unes sur les autres. Si vous affichez deux contrôles au même endroit,
c'est le dernier créé qui sera visible.
Selon le principe qui veut qu'une fenêtre prenne en charge l'affichage de sa zone client et tous les
événements qui s'y rapportent, vous n'avez plus à gérer l'affichage de votre zone client
occupée par un contrôle fils. Dans l'exemple, nous n'affichons d'ailleurs rien sous la "list box", ni en
réponse à WM_ERASEBKGND ni en réponse à WM_PAINT, c'est inutile. De même tous les
événements souris se rapportant à cette zone seront gérés par la Callback du
contrôle concerné. Faites l'expérience de passer la souris sur le bouton poussoir par exemple, notre
programme ne reçoit plus les messages WM_MOUSEMOVE et donc n'affiche plus les coordonnées souris pour cette zone.
Communication avec les contrôles.
A partir du moment où l'on crée des contrôles Windows pour gérer certaines actions utilisateur,
il faut pouvoir être prévenus, notifiés, ou au moins être en capacité de
récupérer l'information qui découle des ces actions. L'essentiel de la communication entre
contrôles Windows passe par des "Messages". On envoie des messages aux contrôles pour changer leur
état ou leur aspect et l'on reçoit des messages quand le contrôle est manipulé.
Pour envoyer un message, on a grosso modo le choix entre deux fonctions :
- SendMessage(.) qui est une fonction dites "synchrone" car elle est bloquante, c'est un peu comme si
vous appeliez directement la Callback d'un contrôle.
- PostMessage(.) qui est une fonction dites "asynchrone" car elle ne fait que déposer le message
dans la file de messages (Message Queue) et n'attend donc pas la réponse du contrôle visé.
Notons que d'autres API (d'autres fonctions du système) peuvent être l'équivalent d'un envoi de Message.
Par exemple la fonction SetWindowText() qui permet de changer le "WindowName" d'une fenêtre (ou d'un contrôle)
est équivalente à l'utilisation d'un message WM_SETTEXT. Il faut retenir que l'ensemble des contrôles
Windows se gère par l'utilisation de message et qu'il y a un jeu spécifique de messages pour chaque type de
contrôle.
|
Quelques points du source : |
On a conservé l'intégralité du source code de la leçon précédente et
l'on a ajouté une fonction CreateOurControls(.) qui s'occupe de créer nos controles windows dans
notre fenêtre principale. En réponse à WM_ERASEBKGND nous affichons toujours notre Bitmap de
fond mais, comme notre Bitmap ne couvre pas forcément toute la surface, nous dessinons aussi un fond gris
dessous en fonction de la taille courante de notre zone client. Les messages qui nous arrivent des
contrôles Windows sont essentiellement des notifications, donc passent par le message WM_COMMAND que l'on
traite dans notre fonction ManageMenu(.). Dans le paramètre WPARAM sont codés l'ident du contrôle
(dans la partie LOWORD) et l' éventuel message de notification (dans la partie HIWORD).
Pour la List BOX on traite le message de notification LBN_SELCHANGE qui nous arrive à chaque fois que l'utilisateur
choisi un item dans la liste. Pour L'Edit Box on traite le message EN_CHANGE qui nous est transmit à chaque saisie
d'un nouveau caractère. Pour la Combo Box on répond à la notification CBN_SELCHANGE qui est
envoyée quand l'utilisateur sélectionne un autre item de la liste de choix. Le Bouton poussoir
ayant été définit avec l'Ident IDM_ABOUT va avoir la même fonction que l'item du Menu IDM_ABOUT
qui est déjà traité.
Relations entre les contrôles :
La difficulté de notre exemple se situe dans la manière de gérer nos relations entre nos contrôle
et notre Slider, relations que l'on a voulues temps réel, c'est à dire que tout changement est pris en compte
immédiatement. Donc si vous suivez la section WM_MOUSEMOVE vous voyez que pour chaque mouvement du Slider, on va ajouter
une entrée dans la liste box, mettre à jour la boite d'édition et la combo-box.
De même, dès que vous allez taper un caractère dans l'Edit Box, on va recevoir une notification EN_CHANGE
(voir fonction ManageMenu). Après avoir pris connaissance de la nouvelle valeur de notre Slider, on va l'afficher
à sa nouvelle position et mettre à jour le Combo-Box. Donc simplement pour chaque modification sur un
contrôle donné, on va mettre à jour tous les autres contrôles qui dépendent de la
même donnée, ici la valeur de notre Slider. Seule exception, la ListBox sert d'historique de mouvement souris du
Slider et n'est pas mise à jour quand on utilise un autre contrôles que le Slider.
Dans le code source, vous verrez qu'on a fait une gestion au cas par cas, notamment pour faire apparaître clairement
un phénomène de réentrance qu'il faut gérer quand on met en place ce genre de relations
croisées entre contrôles Windows. En effet l'appel à SetWindowText() pour mettre à jour une
EditBox par exemple, va déclencher la notification EN_CHANGE, sans passer par la boucle de messages. Cet notification
EN_CHANGE, si elle est traité comme une action utilisateur, peut déclencher la mise à jour d'autres
contrôles, qui à leur tour, peuvent générer d'autres messages de notification et ainsi de suite...
c'est le blocage par boucle infini où Paul appelle Pierre qui appelle Paul qui rappelle Pierre etc...
Donc pour éviter ce phénomène on met en place des variables d'état que l'on appelle drapeau
(flag en anglais) telles que fMoveSlider, fUpdateFromComboBox, fUpdateFromEditBox, pour savoir qu'est ce qu'on est en train de
faire, et différencier une notification qui serait le produit d'une action utilisateur d'une notification qui découle
d'une mise à jour par programme. Contre exemple : dans la gestion de notre ListBox, en réponse à
LBN_SELCHANGE on se sert de cette réentrance pour mettre à jour tout le monde en faisant seulement un
SetWindowText(lpapp->hw_EditBox...) parce que l'on sait que cet appel va engendrer un EN_CHANGE qui va mettre
à jour la position du Slider et le ComboBox.
Le menu contextuel :
Le menu contextuel n'est pas un contrôle (il a un peu les mêmes propriétés 'popup' que la
DialogBox) mais constitue une manière assez pratique de permettre à l'utilisateur de changer des
données ou de faire des actions. Il y'a tout un jeu d'API pour fabriquer des menus, nous utiliserons que
CreatePopupMenu(), AppendMenu() et pour l'afficher : la fonction TrackPopupMenu() que nous appelons sur le message WM_RBUTTONDOWN.
|
Questions / Réponses: |
Quand on redimensionne notre fenêtre, comment les contrôles sont repositionnés / redimensionnés ?
En réponse au message WM_SIZE, on repositionne ou redimensionne nos contrôles à l'aide de la fonction
SetWindowPos(...).
atof ? que fait cette fonction ?
C'est une fonction 'C' générique qui convertie une chaîne de caractères en une valeur
numérique réelle (double ou float).
Dans le source tools.c la fonction TOOL_MemZERO semble être défini dans un autre langage ?
C'est de l'assembleur inline, et cette fonction, qui met à zéro une plage mémoire définit
par un pointeur (target) et une taille (nbByte), constitue une bonne introduction à l'usage de l'assembleur dans
un programme en C/C++ avec les outils Microsoft.
Qu'est ce que la "Ré-Entrance" ?
Pour une fonction donnée, la réentrance est l'action d'être rappelé avant d'être
sortie de la fonction (avant la fin de la fonction). Dans notre exemple, vous pouvez tracer l'action de l'utilisateur qui
sélectionne un item dans la ListBox. Notre Callback est d'abord appelée pour un LBN_SELCHANGE, pour lequel
on fait un SetWindowText(lpapp->hw_EditBox,sss); mais cet appel va engendrer une réentrance : notre Callback
va être rappelée avec la notification EN_CHANGE. Ce n'est qu'après le traitement EN_CHANGE que le
code concernant LBN_SELCHANGE se finira.
|
Source : minprg.c |
/*--------------------------------------------------------------------------------*/
/* 'C' Programming Under WIN32 V.Burel (c)2008*/
/* */
/* WEB : http://pagesperso-orange.fr/vb-audio/fr/pub/programming/index.htm */
/*--------------------------------------------------------------------------------*/
/* This MinPrg is a minimal program under windows (like a Hello World) */
/* To demonstrate how to use basic Windows Control */
/* Edit Box, Push Button, Combo Box, List Box and contextual popup menu */
/*--------------------------------------------------------------------------------*/
/* To compile With Microsoft VC2005 you need to create an empty Win32 project */
/* with the following options : */
/* - Configuration Properties / General : Char Set = NOT SET */
/* - Configuration Properties / C/C++ / Preprocessor : _CRT_SECURE_NO_DEPRECATE */
/*--------------------------------------------------------------------------------*/
#ifndef __cplusplus
#ifndef STRICT
#define STRICT
#endif
#endif
#include <windows.h>
#include <stdio.h>
#include "minprg.h"
#include "tools.h"
//
//define globals
//
static HWND G_hwnd_MainWindow =NULL;
static HINSTANCE G_hinstance =NULL;
// we create a strcuture to store GDI Resources.
typedef struct tagCOLORPENBRUSH
{
COLORREF color;
HPEN pen;
HBRUSH brush;
} T_COLORPENBRUSH, *PT_COLORPENBRUSH, *LPT_COLORPENBRUSH;
//we create a main structure and data to store application data.
typedef struct tagAPP_CONTEXT
{
//resources
HBITMAP bmp_bkg;
HBITMAP bmp_cursor;
HFONT font_small;
HFONT font_med;
HFONT font_big;
T_COLORPENBRUSH gdiobjects_gray1;
T_COLORPENBRUSH gdiobjects_gray2;
T_COLORPENBRUSH gdiobjects_bleu;
T_COLORPENBRUSH gdiobjects_red;
//controls:
HWND hw_ListBox;
HWND hw_EditBox;
HWND hw_ComboBox;
HWND hw_PushButton;
HMENU hPopupMenu;
long nbHistoryValue;
BOOL fUpdateFromEditBox;
BOOL fUpdateFromComboBox;
//data
long mouse_x, mouse_y;
float slider_value;
long lastmouse_x;
HWND LastCapture;
BOOL fMoveSlider;
} T_APP_CONTEXT, *PT_APP_CONTEXT, *LPT_APP_CONTEXT;
static T_APP_CONTEXT G_MainAppCtx;
/*******************************************************************************/
/** INIT / END Resources **/
/*******************************************************************************/
long CreateColorPenBrush(LPT_COLORPENBRUSH lpgdi, COLORREF color)
{
LOGBRUSH lb;
if (lpgdi == NULL) return -1;
lpgdi->color=color;
lpgdi->pen=CreatePen(PS_SOLID,0,color);
lb.lbStyle=BS_SOLID;
lb.lbColor=color;
lpgdi->brush=CreateBrushIndirect(&lb);
return 0;
}
long DestroyColorPenBrush(LPT_COLORPENBRUSH lpgdi)
{
if (lpgdi == NULL) return -1;
lpgdi->color=0;
if (lpgdi->pen != NULL) DeleteObject(lpgdi->pen);
lpgdi->pen=NULL;
if (lpgdi->brush != NULL) DeleteObject(lpgdi->brush);
lpgdi->brush=NULL;
return 0;
}
long InitResources(LPT_APP_CONTEXT lpapp)
{
LOGFONT lf;
if (lpapp == NULL) return -1;
//Load Bitmap Resources
lpapp->bmp_bkg =LoadBitmap(G_hinstance,MAKEINTRESOURCE(100));
lpapp->bmp_cursor =LoadBitmap(G_hinstance,MAKEINTRESOURCE(101));
//make Font
memset(&lf,0, sizeof(LOGFONT));
lf.lfHeight = 14;
lf.lfWeight = 400;
strcpy(lf.lfFaceName,"Arial");
lpapp->font_small =CreateFontIndirect(&lf);
lf.lfHeight = 22;
lf.lfWeight = 400;
strcpy(lf.lfFaceName,"Arial");
lpapp->font_med =CreateFontIndirect(&lf);
lf.lfHeight = 40;
lf.lfWeight = 400;
strcpy(lf.lfFaceName,"Arial");
lpapp->font_big =CreateFontIndirect(&lf);
//make pen brush
CreateColorPenBrush(&(lpapp->gdiobjects_gray1), RGB(100,100,100));
CreateColorPenBrush(&(lpapp->gdiobjects_gray2), RGB(150,150,150));
CreateColorPenBrush(&(lpapp->gdiobjects_bleu), RGB(0,0,250));
CreateColorPenBrush(&(lpapp->gdiobjects_red), RGB(255,0,0));
return 0;
}
long EndResources(LPT_APP_CONTEXT lpapp)
{
if (lpapp == NULL) return -1;
//Delete Bitmap Object
if (lpapp->bmp_bkg != NULL) DeleteObject(lpapp->bmp_bkg);
lpapp->bmp_bkg=NULL;
if (lpapp->bmp_cursor != NULL) DeleteObject(lpapp->bmp_cursor);
lpapp->bmp_cursor=NULL;
//Delete font Object
if (lpapp->font_small != NULL) DeleteObject(lpapp->font_small);
lpapp->font_small=NULL;
if (lpapp->font_med != NULL) DeleteObject(lpapp->font_med);
lpapp->font_med=NULL;
if (lpapp->font_big != NULL) DeleteObject(lpapp->font_big);
lpapp->font_big=NULL;
//Delete Pen Brush
DestroyColorPenBrush(&(lpapp->gdiobjects_gray1));
DestroyColorPenBrush(&(lpapp->gdiobjects_gray2));
DestroyColorPenBrush(&(lpapp->gdiobjects_bleu));
DestroyColorPenBrush(&(lpapp->gdiobjects_red));
return 0;
}
/*******************************************************************************/
/** QUIT & ABOUT **/
/*******************************************************************************/
void ManageCloseMessage(HWND hw)
{
int rep;
char titre[]="Close Application...";
char message[512];
//Get the string from resource, otherwise we use a constant.
if (LoadString(G_hinstance, IDS_CONFIRMCLOSE, message, 512) == 0)
strcpy(message,"Do you Want To Close This Application ?\n"
"(but there is a problem to load resources)");
//Open System Dialog Box
rep=MessageBox(hw,message,titre,MB_APPLMODAL | MB_YESNO | MB_ICONQUESTION);
if (rep == IDNO) return;
PostMessage(hw,WM_DESTROY,0,0L); //DestroyWindow(G_hwnd_MainWindow);
}
void ManageAboutBox(HWND hw)
{
char titre[]="About...";
char message[512];
strcpy(message,SZPUBLICNAME);
strcat(message,"\nVersion : ");
strcat(message,SZPUBLICVERSION);
strcat(message,"\nStandalone Application\n");
strcat(message,"\nExample of 'C' Source code\n");
MessageBox(hw,message,titre,MB_APPLMODAL | MB_OK | MB_ICONINFORMATION);
}
/*******************************************************************************/
/*******************************************************************************/
/*******************************************************************************/
BOOL InitSoftware(HWND hw)
{
InitResources(&G_MainAppCtx);
return TRUE;
}
BOOL EndSoftware(HWND hw)
{
EndResources(&G_MainAppCtx);
return TRUE;
}
/*******************************************************************************/
/* Display information in LCD */
/*******************************************************************************/
void DisplayMousePosition(LPT_APP_CONTEXT lpapp, HDC dc)
{
char sss[64];
long dx,dy;
RECT rect;
HFONT oldfont;
//let's define some local data
dx=190;
dy=34;
rect.left = 297;
rect.top=14;
rect.right=rect.left+dx;
rect.bottom=rect.top+dy;
//Draw background by using bitmap
TOOL_DrawPartOfBitmap(dc, lpapp->bmp_bkg, rect.left,rect.top, rect.left,rect.top,dx,dy);
//Draw X
oldfont=(HFONT)SelectObject(dc,lpapp->font_med);
SetTextColor(dc,lpapp->gdiobjects_gray1.color);
SetBkMode(dc,TRANSPARENT);
strcpy(sss,"x:");
TextOut(dc,rect.left,rect.top+12,sss,(int)strlen(sss));
sprintf(sss,"%i",lpapp->mouse_x);
SelectObject(dc,lpapp->font_big);
SetTextColor(dc,lpapp->gdiobjects_gray2.color);
TextOut(dc,rect.left+15,rect.top,sss,(int)strlen(sss));
//Draw Y
rect.left +=100;
SelectObject(dc,lpapp->font_med);
SetTextColor(dc,lpapp->gdiobjects_gray1.color);
strcpy(sss,"y:");
TextOut(dc,rect.left,rect.top+12,sss,(int)strlen(sss));
sprintf(sss,"%i",lpapp->mouse_y);
SelectObject(dc,lpapp->font_big);
SetTextColor(dc,lpapp->gdiobjects_gray2.color);
TextOut(dc,rect.left+15,rect.top,sss,(int)strlen(sss));
//replace previous GDI object in DC
SelectObject(dc,oldfont);
}
void DisplaySlider(LPT_APP_CONTEXT lpapp, HDC dc)
{
float fmin,fmax,fratio;
long dx_curs;
long dx,dy,xx;
RECT rect;
//let's define some local data
dx=250; //width of the slider
dy=18; //height of the slider
rect.left =13; //position of the slider in the Client Area
rect.top =24;
rect.right=rect.left+dx;
rect.bottom=rect.top+dy;
//compute Cursor coordinates
dx_curs=34;
fmin=-24.0f;
fmax=+24.0f;
fratio=(dx-dx_curs)/(fmax-fmin);
xx=(long)((lpapp->slider_value-fmin)*fratio);
if (xx<0) xx=0;
if (xx>(dx-dx_curs)) xx=dx-dx_curs;
//Draw Slider and Cursor in 3 steps to minimize flickering effects.
if (xx>0) TOOL_DrawPartOfBitmap(dc, lpapp->bmp_bkg, rect.left,rect.top, rect.left,rect.top,xx,dy);
TOOL_DrawBitmap(dc,rect.left+xx,rect.top,lpapp->bmp_cursor);
if ((xx+dx_curs)<dx) TOOL_DrawPartOfBitmap(dc, lpapp->bmp_bkg, rect.left+xx+dx_curs,rect.top,
rect.left+xx+dx_curs,rect.top,dx-(xx+dx_curs),dy);
}
void DisplaySliderValueInLCD(LPT_APP_CONTEXT lpapp, HDC dc)
{
HFONT oldfont;
char sss[128];
long dx,dy;
RECT rect;
//let's define some local data
dx=190;
dy=16;
rect.left = 297;
rect.top=52;
rect.right=rect.left+dx;
rect.bottom=rect.top+dy;
//Draw background of the slider using bmp
TOOL_DrawPartOfBitmap(dc, lpapp->bmp_bkg, rect.left,rect.top, rect.left,rect.top,dx,dy);
//Draw value
oldfont=(HFONT)SelectObject(dc,lpapp->font_small);
SetTextColor(dc,lpapp->gdiobjects_red.color);
SetBkMode(dc,TRANSPARENT);
sprintf(sss,"Slider Value = %0.2f",lpapp->slider_value);
DrawText(dc,sss,(int)strlen(sss),&rect,DT_SINGLELINE | DT_LEFT | DT_VCENTER);
//replace previous GDI object in DC
SelectObject(dc,oldfont);
}
void DisplayOurStuff(LPT_APP_CONTEXT lpapp, HDC dc)
{
DisplayMousePosition(lpapp,dc);
DisplaySlider(lpapp,dc);
DisplaySliderValueInLCD(lpapp, dc);
}
/*******************************************************************************/
/** Manage Menu **/
/*******************************************************************************/
static float extractValueFromListString(char *lpchar)
{
float ff;
while ((*lpchar != 0) && (*lpchar != '=')) lpchar++;
if (*lpchar != '=') return 0.0f;
lpchar++;
if (*lpchar == 0) return 0.0f;
ff=(float)atof(lpchar);
return ff;
}
void IMAIN_ProcessPopupCommand(HWND hparent, int nuCommand)
{
char sss[1024];
switch(nuCommand)
{
case IDM_CTXPOPUP_INFO:
TOOL_GetAppDirectory(sss);
TOOL_GetPathOnly(sss);
ShellExecute(hparent,"open","readme.txt",NULL,sss,SW_SHOW );
break;
case IDM_CTXPOPUP_WEB:
ShellExecute(hparent,"open","http://www.vb-audio.com",NULL,NULL,SW_SHOW );
break;
case IDM_CTXPOPUP_MAIL:
ShellExecute(hparent,"open","mailto:vincent.burel@nospam-vb-audio.com",NULL,NULL,SW_SHOW );
break;
}
}
void ManageMenu(LPT_APP_CONTEXT lpapp, HWND hw, WPARAM p,LPARAM w)
{
char sss[256];
float ff;
HPEN oldpen;
HBRUSH oldbrush;
long vi,x0,y0,nuCommand, nNotify,iSelect;
HDC dc;
nuCommand=(long)LOWORD(p);
nNotify =(long)HIWORD(p);
switch(nuCommand)
{
case IDM_DRAWSOMETHING:
dc=GetDC(hw);
x0=300;
y0=80;
//Draw pixel.
for (vi=0;vi<255;vi=vi+4)
{
SetPixel(dc,x0+(vi>>1),y0,RGB(vi,0,255-vi));
SetPixel(dc,x0+1+(vi>>1),y0+1,RGB(vi,10,255-vi));
SetPixel(dc,x0+(vi>>1),y0+2,RGB(vi,20,255-vi));
SetPixel(dc,x0+1+(vi>>1),y0+3,RGB(vi,30,255-vi));
}
//Draw line.
x0=x0+150;
oldpen=(HPEN)SelectObject(dc,GetStockObject(BLACK_PEN));
for (vi=0;vi<16;vi++)
{
MoveToEx(dc,x0+(vi<<1),y0,NULL);
LineTo(dc,x0+(vi<<1),y0+4+vi);
}
//Draw empty rectangle
x0=300;
y0=90;
oldbrush=SelectObject(dc,GetStockObject(NULL_BRUSH));
Rectangle(dc,x0,y0,x0+20,y0+20);
x0=x0+25;
RoundRect(dc,x0,y0,x0+20,y0+20,5,5);
//Draw empy circle
x0=x0+25;
Ellipse(dc,x0,y0,x0+20,y0+20);
//Draw full rectangle
SelectObject(dc,GetStockObject(WHITE_BRUSH));
x0=x0+30;
Rectangle(dc,x0,y0,x0+20,y0+20);
x0=x0+25;
RoundRect(dc,x0,y0,x0+20,y0+20,5,5);
//Draw full circle
x0=x0+25;
Ellipse(dc,x0,y0,x0+20,y0+20);
//always select old objects, before releasing a DC.
SelectObject(dc,oldpen);
SelectObject(dc,oldbrush);
ReleaseDC(hw,dc);
break;
case IDM_QUIT:
ManageCloseMessage(hw);
break;
case IDM_ABOUT:
ManageAboutBox(hw);
break;
//manage control
case IDC_LISTBOX:
if (nNotify == LBN_SELCHANGE) //something changed in the combo Box
{
//here the change comes from slider
if (lpapp->fMoveSlider == TRUE) break;
//get Text from List Box Select Item
iSelect=(long)SendMessage(lpapp->hw_ListBox, LB_GETCURSEL,0, 0);
sss[0]=0;
SendMessage(lpapp->hw_ListBox, LB_GETTEXT,(WPARAM)iSelect, (LPARAM)sss);
ff=extractValueFromListString(sss);
if (ff<-24.0f) ff=-24.0f;
if (ff>24.0f) ff=24.0f;
//let's update the Edit Box, this will update other controle
sprintf(sss,"%0.2f",ff);
SetWindowText(lpapp->hw_EditBox,sss);
}
break;
case IDC_EDITBOX:
if (nNotify == EN_CHANGE) //something changed in the Edit Box
{
//here the value is already updated by slider
if (lpapp->fMoveSlider == TRUE) break;
//here the value is already updated by combo
if (lpapp->fUpdateFromComboBox == TRUE) break;
//get new string in Edit Box
GetWindowText(lpapp->hw_EditBox,sss,32);
sss[32]=0;
//convert to float and bind value
ff=(float)atof(sss);
if (ff<-24.0f) ff=-24.0f;
if (ff>24.0f) ff=24.0f;
//update slider value and display it
lpapp->slider_value=ff;
dc=GetDC(hw);
DisplaySlider(lpapp,dc);
DisplaySliderValueInLCD(lpapp, dc);
ReleaseDC(hw,dc);
//update combo Box
lpapp->fUpdateFromEditBox=TRUE;
if (lpapp->slider_value == -24.0f) SendMessage(lpapp->hw_ComboBox,CB_SETCURSEL ,0,0L);
else
{
if (lpapp->slider_value == +24.0f) SendMessage(lpapp->hw_ComboBox,CB_SETCURSEL ,2,0L);
else SendMessage(lpapp->hw_ComboBox,CB_SETCURSEL ,1,0L);
}
lpapp->fUpdateFromEditBox=FALSE;
}
break;
case IDC_COMBOBOX:
if (nNotify == CBN_SELCHANGE) //something changed in the combo Box
{
//here the value is already updated by slider
if (lpapp->fMoveSlider == TRUE) break;
//here the value is already updated by Edit Box
if (lpapp->fUpdateFromEditBox == TRUE) break;
iSelect=(long)SendMessage(lpapp->hw_ComboBox, CB_GETCURSEL,0, 0);
//update slider value and siplay it
if (iSelect == 0) lpapp->slider_value=-24.0f;
if (iSelect == 1) lpapp->slider_value=0.0f;
if (iSelect == 2) lpapp->slider_value=+24.0f;
//update slider value and display it
dc=GetDC(hw);
DisplaySlider(lpapp,dc);
DisplaySliderValueInLCD(lpapp, dc);
ReleaseDC(hw,dc);
//update Edit Box
lpapp->fUpdateFromComboBox=TRUE;
sprintf(sss,"%0.2f",lpapp->slider_value);
SetWindowText(lpapp->hw_EditBox,sss);
lpapp->fUpdateFromComboBox=FALSE;
}
break;
//manage Contextual Popup
default:
IMAIN_ProcessPopupCommand(hw, nuCommand);
break;
}
}
/*******************************************************************************/
/* Create Basic Window Controls */
/*******************************************************************************/
static long CreateOurControls(LPT_APP_CONTEXT lpapp, HWND hw)
{
char sss[256];
//create a list box on the right.
lpapp->hw_ListBox=CreateWindowEx(WS_EX_CLIENTEDGE,"listbox",NULL,
WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_VSCROLL
| LBS_NOTIFY | LBS_NOINTEGRALHEIGHT,
507,0,100,300,
hw,(HMENU)IDC_LISTBOX,G_hinstance,NULL);
if (lpapp->hw_ListBox ==NULL) return -1;
SendMessage(lpapp->hw_ListBox,WM_SETFONT,(WPARAM)lpapp->font_small,MAKELPARAM(1,0));
//Create an Edit Box on the bottom :
strcpy(sss,"0.0");
lpapp->hw_EditBox=CreateWindowEx(WS_EX_CLIENTEDGE,"edit",sss,
WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP,
10,150,100,30,
hw,(HMENU)IDC_EDITBOX,G_hinstance,NULL);
if (lpapp->hw_EditBox ==NULL) return -1;
SendMessage(lpapp->hw_EditBox,WM_SETFONT,(WPARAM)lpapp->font_med,MAKELPARAM(1,0));
SendMessage(lpapp->hw_EditBox,EM_SETMARGINS,EC_LEFTMARGIN | EC_RIGHTMARGIN,(LPARAM) MAKELONG(2,2));
//Create a combo box
lpapp->hw_ComboBox=CreateWindowEx(WS_EX_CLIENTEDGE,"combobox",NULL,
WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST,
120,150,150,300,
hw,(HMENU)IDC_COMBOBOX,G_hinstance,NULL);
if (lpapp->hw_ComboBox ==NULL) return -1;
SendMessage(lpapp->hw_ComboBox,WM_SETFONT,(WPARAM)lpapp->font_med,MAKELPARAM(1,0));
strcpy(sss,"Min Value");
SendMessage(lpapp->hw_ComboBox,CB_ADDSTRING,0,(LPARAM)sss);
strcpy(sss,"Intermediate...");
SendMessage(lpapp->hw_ComboBox,CB_ADDSTRING,0,(LPARAM)sss);
strcpy(sss,"Max Value");
SendMessage(lpapp->hw_ComboBox,CB_ADDSTRING,0,(LPARAM)sss);
SendMessage(lpapp->hw_ComboBox,CB_SETCURSEL ,1,0L);
//Create Push Button
lpapp->hw_PushButton=CreateWindow("button","About Box",WS_CHILD | WS_VISIBLE | WS_TABSTOP,
300,150,150,30,
hw,(HMENU)IDM_ABOUT,G_hinstance,NULL);
if (lpapp->hw_PushButton ==NULL) return -1;
SendMessage(lpapp->hw_PushButton,WM_SETFONT,(WPARAM)lpapp->font_med,MAKELPARAM(1,0));
//Create Contextual Popup Menu
lpapp->hPopupMenu=CreatePopupMenu();
if (lpapp->hPopupMenu ==NULL) return -1;
strcpy(sss,"info...");
AppendMenu(lpapp->hPopupMenu,MF_STRING,IDM_CTXPOPUP_INFO,sss);
strcpy(sss,"See VB's Web Pages...");
AppendMenu(lpapp->hPopupMenu,MF_STRING,IDM_CTXPOPUP_WEB,sss);
strcpy(sss,"E-mail me...");
AppendMenu(lpapp->hPopupMenu,MF_STRING,IDM_CTXPOPUP_MAIL,sss);
return 0;
}
static void DestroyOurControls(LPT_APP_CONTEXT lpapp)
{
DestroyWindow(lpapp->hw_ListBox);
DestroyWindow(lpapp->hw_EditBox);
DestroyWindow(lpapp->hw_ComboBox);
DestroyWindow(lpapp->hw_PushButton);
DestroyMenu(lpapp->hPopupMenu);
}
/*******************************************************************************/
/* CALL BACK */
/*******************************************************************************/
LRESULT CALLBACK MainWindowManageEvent(HWND hw, //handle of the window.
UINT msg, //Message Ident.
WPARAM p1, //parameter 1.
LPARAM p2) //parameter 2
{
LPT_APP_CONTEXT lpapp;
WPARAM vv;
POINT po;
HPEN oldpen;
HBRUSH oldbrush;
HFONT oldfont;
float ff;
RECT rect;
long xx,yy,bmpdx,bmpdy;
long dx,dy,rep;
char sss[256];
HDC dc;
PAINTSTRUCT ps;
lpapp=&G_MainAppCtx;
switch (msg)
{
case WM_CREATE:
//return -1 here cancel the window creation
if (InitSoftware(hw) == FALSE) return -1;
rep=CreateOurControls(lpapp, hw);
//if there is a problem :
if (rep != 0)
{
MessageBox(NULL,"Failed to create Controls...","Application error",
MB_APPLMODAL | MB_OK | MB_ICONERROR);
return -1;
}
break;
case WM_COMMAND:
ManageMenu(lpapp, hw,p1,p2);
break;
case WM_SIZE:
//position control after window re-sizing
dx=(long)LOWORD(p2);
dy=(long)HIWORD(p2);
TOOL_GetBitmapSize(lpapp->bmp_bkg,&bmpdx,&bmpdy);
//position List
xx=dx-bmpdx;
if (xx<100) xx=100;
yy=dy;
if (yy<100) yy=100;
SetWindowPos(lpapp->hw_ListBox,HWND_TOP,bmpdx,0, xx,yy, SWP_NOMOVE | SWP_SHOWWINDOW);
//Position EditBox, Combo and Button on bottom
yy=dy-40;
if (yy<150) yy=150;
SetWindowPos(lpapp->hw_EditBox,HWND_TOP,10,yy, 0,0, SWP_NOSIZE | SWP_SHOWWINDOW);
SetWindowPos(lpapp->hw_ComboBox,HWND_TOP,120,yy, 0,0, SWP_NOSIZE | SWP_SHOWWINDOW);
SetWindowPos(lpapp->hw_PushButton,HWND_TOP,300,yy, 0,0, SWP_NOSIZE | SWP_SHOWWINDOW);
break;
case WM_PAINT:
dc=BeginPaint(hw,&ps);
strcpy(sss,"This Text Is always displayed");
TextOut(dc,10,70,sss,(int)strlen(sss));
SetBkMode(dc,TRANSPARENT);
strcpy(sss,"This Text lets you see the background...");
TextOut(dc,10,90,sss,(int)strlen(sss));
DisplayOurStuff(lpapp,dc);
EndPaint(hw,&ps);
break;
case WM_LBUTTONDOWN:
xx=(long)LOWORD(p2);
yy=(long)HIWORD(p2);
//test if it's in the slider.
rect.left =13-1;
rect.top =24-1;
rect.right=rect.left+250+2;
rect.bottom=rect.top+18+2;
if ((xx>rect.left) && (xx<rect.right) && (yy>rect.top) && (yy<rect.bottom))
{
lpapp->LastCapture=SetCapture(hw);
lpapp->fMoveSlider=TRUE;
lpapp->lastmouse_x=xx;
break;
}
//otherwise display the name of the pressed key.
sss[0]=0;
if ((p1 & MK_CONTROL) != 0) strcat(sss,"CTRL ");
if ((p1 & MK_SHIFT) != 0) strcat(sss,"SHIFT ");
rect.left=xx;
rect.top=yy;
rect.right=rect.left+100;
rect.bottom=rect.top+20;
dc=GetDC(hw);
oldpen=(HPEN)SelectObject(dc,GetStockObject(WHITE_PEN));
oldbrush=(HBRUSH)SelectObject(dc,lpapp->gdiobjects_bleu.brush);
Rectangle(dc,rect.left,rect.top,rect.right,rect.bottom);
oldfont=(HFONT)SelectObject(dc,lpapp->font_med);
SetTextColor(dc,RGB(255,255,255));
SetBkMode(dc,TRANSPARENT);
DrawText(dc,sss,(int)strlen(sss),&rect,DT_SINGLELINE | DT_CENTER | DT_VCENTER);
SelectObject(dc,oldbrush);
SelectObject(dc,oldpen);
SelectObject(dc,oldfont);
ReleaseDC(hw,dc);
break;
case WM_LBUTTONUP:
if (lpapp->fMoveSlider == TRUE)
{
ReleaseCapture();
if (lpapp->LastCapture != NULL) SetCapture(lpapp->LastCapture);
lpapp->fMoveSlider=FALSE;
}
break;
case WM_MOUSEMOVE:
xx=(long)(short int)LOWORD(p2);
yy=(long)(short int)HIWORD(p2);
//display mouse position in real time
lpapp->mouse_x=xx;
lpapp->mouse_y=yy;
dc=GetDC(hw);
DisplayMousePosition(lpapp, dc);
ReleaseDC(hw,dc);
//check if we are moving the slider.
if (lpapp->fMoveSlider == TRUE)
{
ff=(float)(xx-lpapp->lastmouse_x)*0.1f;
if (ff != 0.0f)
{
lpapp->slider_value +=ff;
if (lpapp->slider_value < -24.0f) lpapp->slider_value=-24.0f;
if (lpapp->slider_value > 24.0f) lpapp->slider_value=24.0f;
dc=GetDC(hw);
DisplaySlider(lpapp, dc);
DisplaySliderValueInLCD(lpapp, dc);
ReleaseDC(hw,dc);
//add Value in List Box
lpapp->nbHistoryValue++;
sprintf(sss,"[%04i] Slider Value = %0.3f",lpapp->nbHistoryValue, lpapp->slider_value);
vv=(WPARAM)SendMessage(lpapp->hw_ListBox,LB_ADDSTRING,0,(LPARAM)sss);
SendMessage(lpapp->hw_ListBox,LB_SETCURSEL,vv,0);
//update Edit Box
sprintf(sss,"%0.1f",lpapp->slider_value);
SetWindowText(lpapp->hw_EditBox,sss);
//update combo Box
if (lpapp->slider_value == -24.0f)
SendMessage(lpapp->hw_ComboBox,CB_SETCURSEL ,0,0L);
else
{
if (lpapp->slider_value == +24.0f)
SendMessage(lpapp->hw_ComboBox,CB_SETCURSEL ,2,0L);
else SendMessage(lpapp->hw_ComboBox,CB_SETCURSEL ,1,0L);
}
}
lpapp->lastmouse_x=xx;
}
break;
case WM_RBUTTONDOWN:
po.x=(int)(short int)LOWORD(p2);
po.y=(int)(short int)HIWORD(p2);
ClientToScreen(hw,&po);
TrackPopupMenu(lpapp->hPopupMenu,0,po.x,po.y,0,hw,NULL);
break;
case WM_CLOSE:
ManageCloseMessage(hw);
break;
//here we display the background of our client area.
case WM_ERASEBKGND:
dc=(HDC)p1;
//display background bitmap on the top-left
TOOL_DrawBitmap(dc, 0, 0, lpapp->bmp_bkg);
//draw gray background below the bitmap according the client area size
TOOL_GetBitmapSize(lpapp->bmp_bkg,&bmpdx,&bmpdy);
GetClientRect(hw,&rect);
dx=rect.right-rect.left;
dy=rect.bottom-rect.top;
if (dx>bmpdx) dx=bmpdx;
dy=dy-bmpdy;
if (dy>0)
{
oldpen=(HPEN)SelectObject(dc,GetStockObject(NULL_PEN));
oldbrush=(HBRUSH)SelectObject(dc,GetStockObject(GRAY_BRUSH));
Rectangle(dc,0,bmpdy,dx+1,bmpdy+dy);
SelectObject(dc,oldbrush);
SelectObject(dc,oldpen);
}
return 1;
case WM_DESTROY:
EndSoftware(hw);
DestroyOurControls(lpapp);
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hw,msg,p1,p2));
}
return (0L);
}
/*******************************************************************************/
/** MAIN PROCDURE **/
/*******************************************************************************/
int APIENTRY WinMain(HINSTANCE handle_app, //Application hinstance.
HINSTANCE handle_prev, //NULL.
LPTSTR param, //Command Line Parameter.
int com_show) //How to display window (optionnal).
{
long wstyle;
MSG msg;
char szWindowClassName[]="MainWindowClass";
char * title="Sorry";
WNDCLASS wc;
//we first store the APP Hinstance
G_hinstance=handle_app;
//here you can make some early initialization and analyze command line if any.
TOOL_MemZERO(&G_MainAppCtx, sizeof(T_APP_CONTEXT)); //initialize our structure with ZERO value
TOOL_StoreOriginalAppDirectory();
//we define a window class to create a window from this class
wc.style =CS_HREDRAW | CS_VREDRAW; //property.
wc.lpfnWndProc=(WNDPROC)MainWindowManageEvent; //Adresse of our Callback.
wc.cbClsExtra =0; //to store byte inside a class object.
wc.cbWndExtra =0; //to store byte inside a window object.
wc.hInstance =handle_app; //handle of the application hinstance.
wc.hIcon =LoadIcon(NULL, IDI_APPLICATION); //handle of icon displayed in the caption.
wc.hCursor =LoadCursor(NULL,IDC_ARROW); //handle of cursor mouse .
wc.hbrBackground=(HBRUSH)(COLOR_MENU+1); //Background color.
wc.lpszMenuName="MyMainAppMenu"; //pointer on menu defined in resource.
wc.lpszClassName=szWindowClassName; //pointer on class name.
//register class.
if (RegisterClass(&wc)==0)
{
MessageBox(NULL,"Failed to register main class...",title,MB_APPLMODAL | MB_OK | MB_ICONERROR);
return 0;
}
//then we can create a windows from this class.
//Classical Window without Sizing border.
//wstyle=WS_DLGFRAME | WS_OVERLAPPED | WS_VISIBLE | WS_MINIMIZEBOX | WS_SYSMENU;
//classical Main Window
wstyle=WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN;
G_hwnd_MainWindow=CreateWindow(szWindowClassName,// address of registered class name.
SZPUBLICNAME, // address of window name string
wstyle, // window style
CW_USEDEFAULT, // horizontal position of window
CW_USEDEFAULT, // vertical position of window
UI_WIN_DX, // window width
UI_WIN_DY, // window height
NULL, // parent handle is NULL.
NULL, // menu name defined in resource.
handle_app, // handle of application instance
NULL); // address of window-creation data
if (G_hwnd_MainWindow==NULL)
{
MessageBox(NULL,"Failed to create window...",title,MB_APPLMODAL | MB_OK | MB_ICONERROR);
return 0;
}
ShowWindow(G_hwnd_MainWindow,SW_SHOW); //Display the window.
UpdateWindow(G_hwnd_MainWindow); //Send WM_PAINT.
/*---------------------------------------------------------------------------*/
/* Messages Loop. */
/*---------------------------------------------------------------------------*/
while (GetMessage(&msg,NULL,0,0)) //Get Message if any.
{
TranslateMessage(&msg); //Translate the virtuel keys event.
DispatchMessage(&msg); //DispatchMessage to the related window.
}
//here you can make last uninitialization and release
return (int)(msg.wParam);
}
|
Source : minprg.h |
#ifndef __MINPRG_H__
#define __MINPRG_H__
//version information (for program)
#define SZPUBLICVERSION "1.0.0.0" //displayed version in about box
#define SZPUBLICNAME "Basic Windows Controls"//displayed title in main window
//Information for Main window
#define UI_WIN_DX 750
#define UI_WIN_DY 400
//version information (used in resource file)
#define __FILEVERSION__ 1,0,0,0
#define __PRODUCTVERSION__ 1,0,0,0
#define __SZFILEVERSION__ "1, 0, 0, 0\0"
#define __SZPRODUCTVERSION__ "1, 0, 0, 0\0"
#define __COMMENTS__ "Example of source code"
#define __COMPANYNAME__ "Audio Mechanic & Sound Breeder\0"
#define __FILEDESCRIPTION__ "Minimal Windows Application\0"
#define __INTERNALNAME__ "MinPrg"
#define __LEGALCOPYRIGHT__ "Copyright V.Burel©2008\0"
#define __ORIGINALFILENAME__ "MinPrg.EXE\0"
#define __PRODUCTNAME__ "MinPrg\0"
//definitions for MENU
#define IDM_DRAWSOMETHING 50
#define IDM_QUIT 100
#define IDM_ABOUT 101
//definitions for Control
#define IDC_LISTBOX 500
#define IDC_EDITBOX 501
#define IDC_COMBOBOX 502
//definitions for Popup Menu
#define IDM_CTXPOPUP_INFO 888
#define IDM_CTXPOPUP_WEB 890
#define IDM_CTXPOPUP_MAIL 891
//definitions for STRING-TABLE
#define IDS_CONFIRMCLOSE 100
#endif /*__MINPRG_H__*/
|
Source : minprg.rc |
#include "minprg.h"
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
MyMainAppMenu MENU DISCARDABLE
BEGIN
POPUP "&Command"
BEGIN
MENUITEM "&Draw basic stuff in LCD", IDM_DRAWSOMETHING
MENUITEM SEPARATOR
MENUITEM "&About", IDM_ABOUT
MENUITEM "&Quit", IDM_QUIT
END
END
/////////////////////////////////////////////////////////////////////////////
//
// STRING
//
STRINGTABLE
BEGIN
IDS_CONFIRMCLOSE "Do you want to close this application ?"
END
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap (can be whatever BMP file (2 bits to 24 bits color)
//
100 BITMAP "bkg.bmp"
101 BITMAP "cursor.bmp"
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
1 VERSIONINFO
FILEVERSION __FILEVERSION__
PRODUCTVERSION __PRODUCTVERSION__
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x0L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "000004b0"
BEGIN
VALUE "Comments", __COMMENTS__
VALUE "CompanyName", __COMPANYNAME__
VALUE "FileDescription", __FILEDESCRIPTION__
VALUE "FileVersion", __SZFILEVERSION__
VALUE "InternalName", __INTERNALNAME__
VALUE "LegalCopyright", __LEGALCOPYRIGHT__
VALUE "OriginalFilename", __ORIGINALFILENAME__
VALUE "ProductName", __PRODUCTNAME__
VALUE "ProductVersion", __SZPRODUCTVERSION__
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0, 1200
END
END
|
Source : tools.c |
#ifndef __cplusplus
#ifndef STRICT
#define STRICT
#endif
#endif
#include <windows.h>
#include <stdio.h>
#include "tools.h"
//Make this following define if your compiler does
//not support microsoft inline assembly language:
//#define MY_COMPILER_DOESNOT_SUPPORT_MSASM
/*****************************************************************/
/* Manage Application Directory */
/*****************************************************************/
static char G_CurrentDirectory[1024];
void TOOL_StoreOriginalAppDirectory(void)
{
GetCurrentDirectory(1020,G_CurrentDirectory);
}
void TOOL_GetAppDirectory(char * dir)
{
if (dir != NULL) strcpy(dir,G_CurrentDirectory);
}
void TOOL_GetPathOnly(char * sss)
{
long ll;
ll=(long)strlen(sss);
while ((ll>0) && (sss[ll]!='\\')) ll--;
if (sss[ll] == '\\') sss[ll]=0;
}
/*****************************************************************/
/* Memory Block Functions */
/*****************************************************************/
// Initialize a memory block with ZERO
void __cdecl TOOL_MemZERO(void * target, long nbByte)
{
#ifdef MY_COMPILER_DOESNOT_SUPPORT_MSASM
memset(target,0,nbByte);
#else
__asm {
push edi
push esi
mov eax,DWORD PTR nbByte;
mov edi,DWORD PTR target;
xor edx,edx
cld
mov ecx,eax
shr ecx,3
jz SHORT P_MZ_next1
P_MZ_loop1:
mov DWORD PTR [edi],edx
mov DWORD PTR [edi+0x00000004],edx
add edi,0x00000008
dec ecx
jnz SHORT P_MZ_loop1
P_MZ_next1:
and eax,0x00000007
jz SHORT P_MZ_end1
mov ecx,eax
xor eax,eax
rep stosb
P_MZ_end1:
pop esi
pop edi
}
#endif
}
/*****************************************************************/
/* Bitmap Functions */
/*****************************************************************/
long TOOL_GetBitmapSize(HBITMAP bmp,long * dx,long * dy)
{
BITMAP bmpinfo;
if (bmp == NULL) return -1;
GetObject(bmp,sizeof(BITMAP),&bmpinfo);
if (dx != NULL) *dx=bmpinfo.bmWidth;
if (dy != NULL) *dy=bmpinfo.bmHeight;
return 0;
}
void TOOL_DrawBitmap(HDC dc, int x0, int y0, HBITMAP hbmp)
{
HBITMAP oldBitmap;
BITMAP bm;
HDC dcmem;
dcmem = CreateCompatibleDC(dc);
oldBitmap=(HBITMAP)SelectObject(dcmem,hbmp);
GetObject(hbmp,sizeof(BITMAP),&bm);
BitBlt(dc,x0,y0,bm.bmWidth,bm.bmHeight,dcmem,0,0,SRCCOPY);
SelectObject(dcmem,oldBitmap);
DeleteDC(dcmem);
}
void TOOL_DrawPartOfBitmap(HDC dc,HBITMAP hbmp,int x0, int y0,int bmpx0,int bmpy0, int bmpcx,int bmpcy)
{
HBITMAP oldBitmap;
HDC bitmapDC;
bitmapDC=CreateCompatibleDC(dc);
oldBitmap=(HBITMAP)SelectObject(bitmapDC,hbmp);
BitBlt(dc,x0,y0,bmpcx,bmpcy,bitmapDC,bmpx0,bmpy0,SRCCOPY);
SelectObject(bitmapDC,oldBitmap);
DeleteDC(bitmapDC);
}
/*****************************************************************/
/* Get Window Metrics Info */
/*****************************************************************/
#ifndef SM_CXPADDEDBORDER
#define SM_CXPADDEDBORDER 92
#endif
typedef struct tagVBNONCLIENTMETRICS
{
UINT cbSize;
int iBorderWidth;
int iScrollWidth;
int iScrollHeight;
int iCaptionWidth;
int iCaptionHeight;
LOGFONT lfCaptionFont;
int iSmCaptionWidth;
int iSmCaptionHeight;
LOGFONT lfSmCaptionFont;
int iMenuWidth;
int iMenuHeight;
LOGFONT lfMenuFont;
LOGFONT lfStatusFont;
LOGFONT lfMessageFont;
int iPaddedBorderWidth;
} VBNONCLIENTMETRICS, *LPVBNONCLIENTMETRICS;
void TOOL_GetMetricInfoWindow(long * win_bordersize, long * win_captiondy,long * win_menudy)
{
long xyadjust=0;
BOOL ok;
VBNONCLIENTMETRICS ncm;
ncm.cbSize=sizeof(VBNONCLIENTMETRICS);
//For Vista
ok=SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(VBNONCLIENTMETRICS),&ncm,0L);
if (ok != 0)
{
xyadjust=ncm.iPaddedBorderWidth+2;
if (win_menudy != NULL) *win_menudy =ncm.iMenuHeight;
if (win_bordersize != NULL) *win_bordersize =xyadjust+ncm.iBorderWidth;
if (win_captiondy != NULL) *win_captiondy =ncm.iCaptionHeight;
return;
}
//For Windows 2000/XP
xyadjust=GetSystemMetrics(SM_CXPADDEDBORDER);
if (win_menudy != NULL) *win_menudy=GetSystemMetrics(SM_CYMENU);
if (win_bordersize != NULL) *win_bordersize= xyadjust+GetSystemMetrics(SM_CXDLGFRAME);
if (win_captiondy != NULL) *win_captiondy=GetSystemMetrics(SM_CYCAPTION);
}
|
Source : tools.h |
#ifndef __TOOLS_H__
#define __TOOLS_H__
#ifdef __cplusplus
extern "C" {
#endif
//Application Directory
void TOOL_StoreOriginalAppDirectory(void);
void TOOL_GetAppDirectory(char * dir);
void TOOL_GetPathOnly(char * sss);
//Memory Block Functions
void __cdecl TOOL_MemZERO(void * target, long nbByte);
//Bitmap Functions
long TOOL_GetBitmapSize(HBITMAP bmp,long * dx,long * dy);
void TOOL_DrawBitmap(HDC dc, int x0, int y0, HBITMAP hbmp);
void TOOL_DrawPartOfBitmap(HDC dc,HBITMAP hbmp,int x0, int y0,int bmpx0,int bmpy0, int bmpcx,int bmpcy);
//Window info functions
void TOOL_GetMetricInfoWindow(long * win_bordersize, long * win_captiondy,long * win_menudy);
//End Of Header.
#ifdef __cplusplus
}
#endif
#endif /*__TOOLS_H__*/
|
|