Programmer en 'C' sous Windows
MinPrg02: Les bases de l'affichage et de la gestion souris.
A partir du moment où nous avons une fenêtre, c'est à dire un objet qui reçoit des
événements utilisateur et qui gère une surface d'affichage, nous pouvons déjà
faire tout un tas de choses amusantes. Le programme suivant, se propose de vous familiariser avec la gestion
de la souris et les fonctions de base de l'affichage.
Les Fichiers |
Organisation du Source Code |
MiniPrg_02.exe (256KB 14-MAR-2008)
MiniPrg_02.zip (79KB 14-MAR-2008)
minprg.h
minprg.c
minprg.rc
tools.h
tools.c
|
|
Que fait ce programme ? : |
Ce programme affiche une fenêtre aux dimensions de la Bitmap de fond et fait plusieurs choses en fonction
d'événements souris :
Le menu permet d'afficher quelques exemples d'utilisation de fonctions basiques de dessin dans la partie qui
ressemble à un LCD.
Le fait de bouger la souris sur la fenêtre provoque l'affichage des coordonnées dans le LCD
(coordonnées relatives au coin haut gauche de la zone client de notre fenêtre).
On peut attraper le curseur du Slider par un clic gauche et ensuite le faire bouger. Cela modifie sa valeur
de manière logique (par pas de 0.1) et l'affiche dans le LCD (en rouge).
Si on clic en dehors du Slider, cela affiche une boite bleu qui dit si la touche CTRL ou SHIFT est
pressée en même temps que le clic souris.
|
Les grands principes évoqués : |
Pour dessiner sous Windows, il faut avoir sous la main des objets GDI : des Bitmap, des Icon, mais aussi,
des Pen (pour faire des lignes), des Brush (pour remplir des surfaces), des Color (pour définir la
couleur de nos objets) et des Font pour écrire nos textes. Le système peut vous fournir des
objets d'affichage (voir fonction GetStockObject par exemple) mais notre programme utilisera que des objets
fabriqués main. Dès le lancement (voir notre fonction InitSoftware), nous chargeons nos 2
Bitmaps (qui sont dans les ressources) et fabriquons 3 fontes et 4 trio d'objets Pen/Brush/Color.
Le principe de l'affichage sous Windows est relativement simple : on obtient une DC (Device Context) sur une zone d'affichage
(généralement la zone client d'une fenêtre, mais ça peut être l'écran entier ou même une
imprimante) et on configure cette DC en fonction de ce qu'on veux faire. Par exemple si l'on veut dessiner un Rectangle, on
va d'abord sélectionner un Pen pour la bordure et une Brush pour la surface, c'est le rôle de la fonction
SelectObject. Si vous ne sélectionnez pas d'objets, les fonctions de dessin utiliseront les objets couramment ou
dernièrement sélectionnés dans cette DC. Un principe fondamentale cependant, consiste à
toujours restaurer les objets d'une DC pour chaque type d'objet GDI : Bitmap, Pen, Brush, Font. Il faut sauvegarder ce que
renvoie la fonction SelectObject (elle renvoie l'ancien objet sélectionné) pour pouvoir le restaurer en fin
d'affichage (avant de rendre la DC au système par un ReleaseDC ou un EndPaint). Et surtout ne pas détruire
un objet d'affichage qui pourrait être sélectionné ou pire en usage dans une DC !
Pour la souris, nous allons traiter 3 nouveaux messages : WM_LBUTTONDOWN, WM_MOUSEMOVE et WM_LBUTTONUP et avec ceux ci, gérer
la logique de déplacement du curseur de notre "Slider". Quand l'utilisateur clic sur le Slider (dont on
connaît les coordonnées) on va considérer que l'utilisateur veux bouger le curseur en bougeant sa
souris horizontalement. Pour se faire nous avons définit 3 variables : fMoveSlider pour indiquer que nous sommes
dans le mode qui consiste à prendre en compte les mouvements souris pour bouger notre curseur. lastmouse_x qui
nous permettra d'évaluer la taille des déplacement entre deux messages WM_MOUSEMOUVE. Et LastCapture qui
stock ce que renvoie la fonction système SetCapture(). Cette dernière fonction est primordiale car elle
permet de capturer les événements souris, garantissant que notre fenêtre recevra les WM_MOUSEMOUVE
et WM_LBUTTONUP même si la souris sort de la fenêtre. Ce qui n'est pas le cas autrement ! Vous avez du le
remarquer, les coordonnées souris sont mises à jour uniquement quand vous bougez la souris dans la zone
cliente de notre fenêtre, en dehors nous ne recevons plus d'événement WM_MOUSEMOUVE. Dès que vous
utilisez le Slider, un SetCapture() est fait, et vous voyez les coordonnées se mettre à jour, même si
la souris est en dehors de la fenêtre.
|
Quelques points du source : |
Dans notre Callback nous répondons à un nouveau Message : WM_ERASEBKGND qui est appelé avant le
WM_PAINT pour afficher le fond. Dans l'exemple précédent, nous n'y répondions pas, c'est la
DefWindowProc qui utilisait la Brush (hbrBackground) de la classe de la fenêtre pour dessiner le fond de la
zone client. Le fait est que ce message est pratique pour afficher les parties statiques d'une interface graphique,
notamment quand cette interface est basée sur une image. Ici nous répondons au message WM_ERASEBKGND
en affichant notre image de fond à l'aide de notre nouvelle fonction : TOOL_DrawBitmap.
TOOL.C et TOOL.H : forment ce que l'on pourrait appeler une "librairie" sous la forme de codes sources,
qui vont venir s'ajouter à notre projet (il faut les inclure dans la compilation). Dans cette librairie, nous
mettrons les fonctions générales qui pourront nous servir dans tout autres programmes sous Windows.
Donc des fonctions dépendantes de Windows (O/S dépendant) mais indépendante de l'application
qui les utilise. Pour l'instant, nous y avons placé les fonctions de gestion de Bitmap et une fonction
TOOL_GetMetricInfoWindow qui tente de trouver les informations sur la taille des bordures, barre de titre et menu d'une
fenêtre classique.
Programmer, c'est d'abord une question d'organisation. Organiser le source dans les fichiers, organiser les
données, les objets, les fonctions, les noms, les préfixes... Petit à petit, nous allons mettre
en place les prémices d'une telle organisation. Vous remarquerez le regroupement de toute nos
données d'application dans la structure G_MainAppCtx de type T_APP_CONTEXT . En 'C' c'est une
première étape pour aller vers un programmation "Orienté Objet" (POO)
|
Questions / Réponses: |
Pourquoi, quand je bouge très vite le curseur du Slider, y'a parfois comme un scintillement.
C'est du "Flickering" c'est du au fait que nous affichons notre Slider avec des "overlap" (des chevauchements
d'images). En effet dans la méthode d'affichage utilisée, certains points (pixels de l'écran)
subissent deux affichages différents. La zone sous le curseur subit d'abord l'affichage du bitmap de fond,
avant de voir celui du Bitmap du curseur. Comme le suggère le schéma ci-dessous, une méthode
convenable consisterait à faire l'affichage en 3 étapes pour éviter l'overlap, d'abord la partie de
tirette à gauche du curseur, ensuite le curseur, enfin la partie de tirette à droite du curseur.
Pourquoi quand j'élargie la taille de la fenêtre il se dessine n'importe quoi ?
Parce que dans cet exemple, nous répondons au message WM_ERASEBKGND et nous ne gérons que la
zone définie par notre Bitmap de fond (507x129). Nous ne tenons pas compte de la taille réelle de
la fenêtre, et nous ne dessinons rien d'autre que notre Bitmap. Donc quand on élargie la fenêtre,
la zone client s'élargie, mais aucun processus ne dessine quoi que ce soit dans les zones autour de notre bitmap,
c'est pourquoi elles comportent n'importe quoi. Une solution consisterait à interdire le re-dimensionnement de
la fenêtre en changeant les styles de création de notre fenêtre principale, voir ligne
commentée : wstyle= WS_DLGFRAME | WS_OVERLAPPED | WS_VISIBLE | WS_MINIMIZEBOX | WS_SYSMENU .
|
Source : minprg.c |
/*--------------------------------------------------------------------------------*/
/* 'C' Programming Under WIN32 V.Burel (c)2007*/
/* */
/* 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 Mouse functions and basic drawing API */
/*--------------------------------------------------------------------------------*/
/* 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;
//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 = 16;
lf.lfWeight = 800;
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;
dy=18;
rect.left =13;
rect.top =24;
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);
//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;
TOOL_DrawBitmap(dc,rect.left+xx,rect.top,lpapp->bmp_cursor);
}
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 **/
/*******************************************************************************/
void ManageMenu(HWND hw, WPARAM p,LPARAM w)
{
HPEN oldpen;
HBRUSH oldbrush;
long vi,x0,y0;
HDC dc;
switch(LOWORD(p))
{
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;
}
}
/*******************************************************************************/
/* CALL BACK */
/*******************************************************************************/
LRESULT CALLBACK MainWindowManageEvent(HWND hw, //handle of the window.
UINT msg, //Message Ident.
WPARAM p1, //parameter 1.
LPARAM p2) //parameter 2
{
HPEN oldpen;
HBRUSH oldbrush;
HFONT oldfont;
float ff;
RECT rect;
long win_bordersize,win_captiondy,win_menudy;
long bmpdx,bmpdy,xx,yy;
char sss[256];
HDC dc;
PAINTSTRUCT ps;
switch (msg)
{
case WM_CREATE:
if (InitSoftware(hw) == FALSE) return -1;
//adjust window size according background bitmap.
TOOL_GetMetricInfoWindow(&win_bordersize, &win_captiondy,&win_menudy);
TOOL_GetBitmapSize(G_MainAppCtx.bmp_bkg,&bmpdx,&bmpdy);
SetWindowPos(hw,HWND_TOP, 0,0,bmpdx+(win_bordersize*2),
bmpdy+win_menudy+win_captiondy+(win_bordersize*2),
SWP_NOMOVE | SWP_SHOWWINDOW);
break;
case WM_COMMAND:
ManageMenu(hw,p1,p2);
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(&G_MainAppCtx,dc);
EndPaint(hw,&ps);
break;
case WM_LBUTTONDOWN:
xx=(long)LOWORD(p2);
yy=(long)HIWORD(p2);
//test if it is 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))
{
G_MainAppCtx.LastCapture=SetCapture(hw);
G_MainAppCtx.fMoveSlider=TRUE;
G_MainAppCtx.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,G_MainAppCtx.gdiobjects_bleu.brush);
Rectangle(dc,rect.left,rect.top,rect.right,rect.bottom);
oldfont=(HFONT)SelectObject(dc,G_MainAppCtx.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 (G_MainAppCtx.fMoveSlider == TRUE)
{
ReleaseCapture();
if (G_MainAppCtx.LastCapture != NULL) SetCapture(G_MainAppCtx.LastCapture);
G_MainAppCtx.fMoveSlider=FALSE;
}
break;
case WM_MOUSEMOVE:
xx=(long)(short int)LOWORD(p2);
yy=(long)(short int)HIWORD(p2);
//display mouse position in real time
G_MainAppCtx.mouse_x=xx;
G_MainAppCtx.mouse_y=yy;
dc=GetDC(hw);
DisplayMousePosition(&G_MainAppCtx, dc);
ReleaseDC(hw,dc);
//check if we are moving the slider.
if (G_MainAppCtx.fMoveSlider == TRUE)
{
ff=(float)(xx-G_MainAppCtx.lastmouse_x)*0.1f;
if (ff != 0.0f)
{
G_MainAppCtx.slider_value +=ff;
if (G_MainAppCtx.slider_value < -24.0f) G_MainAppCtx.slider_value=-24.0f;
if (G_MainAppCtx.slider_value > 24.0f) G_MainAppCtx.slider_value=24.0f;
dc=GetDC(hw);
DisplaySlider(&G_MainAppCtx, dc);
DisplaySliderValueInLCD(&G_MainAppCtx, dc);
ReleaseDC(hw,dc);
}
G_MainAppCtx.lastmouse_x=xx;
}
break;
case WM_CLOSE:
ManageCloseMessage(hw);
break;
//here we display the background of our client area.
case WM_ERASEBKGND:
dc=(HDC)p1;
TOOL_DrawBitmap(dc, 0, 0, G_MainAppCtx.bmp_bkg);
return 1;
case WM_DESTROY:
EndSoftware(hw);
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.
//Zero initialize our main structure.
memset(&G_MainAppCtx, 0, sizeof(T_APP_CONTEXT));
//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 some byte inside a class object.
wc.cbWndExtra =0; //to store some 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_ICONEXCLAMATION);
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;
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 for a main window.
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_ICONEXCLAMATION);
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 "Mouse and Drawing" //displayed title in main window
//Information for Main window
#define UI_WIN_DX 600
#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©2007\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 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 |
/*****************************************************************/
/* TOOLS V.Burel */
/*****************************************************************/
/* General Functions to be used in MinPrg Samples */
/*****************************************************************/
#ifndef __cplusplus
#ifndef STRICT
#define STRICT
#endif
#endif
#include <windows.h>
#include "tools.h"
/*****************************************************************/
/* 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
//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__*/
|
|