Dialogboxindirect avec des controles (win32)

Soyez le premier à donner votre avis sur cette source.

Vue 8 247 fois - Téléchargée 547 fois

Description

Ce code montre comment créer une DialogBox contenant des controles sans utilsier des ressources. Il y a déja des codes utilisant DialogBoxIndirect, mais aucun je crois ne montre la création de controles, grâce à la structure DLGITEMTEMPLATE.

Source / Exemple :


#include <windows.h>
#include <commctrl.h>

#pragma comment(lib, "comctl32.lib")

INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM, LPARAM)
{
  if(uMsg == WM_CLOSE) EndDialog(hDlg, 0);
  return 0;
}

LPWORD CreateControl(LPWORD lpw, DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle,
                     int x, int y, int cx, int cy, int ctlID)
{
  if((LPARAM)lpw & 3) lpw++; // Aligner sur un DWORD
  LPDLGITEMTEMPLATE lpit = (LPDLGITEMTEMPLATE)lpw;
  lpit->x = x;
  lpit->y = y;
  lpit->cx = cx;
  lpit->cy = cy;
  lpit->style = dwStyle;
  lpit->dwExtendedStyle = dwExStyle;
  lpit->id = ctlID;
  lpw = (LPWORD) (lpit + 1);
  lpw += MultiByteToWideChar(CP_ACP, 0, lpClassName, -1, (LPWSTR)lpw, 128);
  if(lpWindowName) lpw += MultiByteToWideChar(CP_ACP, 0, lpWindowName, -1, (LPWSTR)lpw, 128);
  else *lpw++ = 0;

  • lpw++ = 0; // Pas de data
return lpw; } LPWORD CreateDlg(LPWORD lpw, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int cx, int cy, int fontSize, LPCTSTR lpFontName, int ctrlNum) { LPDLGTEMPLATE lpdt = (LPDLGTEMPLATE)lpw; if(!lpFontName) { lpFontName = "Ms Shell Dlg 2"; fontSize = 8; } lpdt->style = dwStyle; lpdt->x = x; lpdt->y = y; lpdt->cx = cx; lpdt->cy = cy; lpdt->cdit = ctrlNum; // Nombre de contrôles lpw = (LPWORD)(lpdt + 1);
  • lpw++ = 0; // Pas de menu
  • lpw++ = 0; // Classe par défaut
if(lpWindowName) lpw += MultiByteToWideChar(CP_ACP, 0, lpWindowName, -1, (LPWSTR)lpw, 128); else *lpw++ = 0;
  • lpw++ = fontSize;
return lpw + MultiByteToWideChar(CP_ACP, 0, lpFontName, -1, (LPWSTR)lpw, 128); } #ifdef _DEBUG int main() #else #pragma comment(linker, "/entry:myWinMain") int __stdcall myWinMain() #endif { InitCommonControls(); HGLOBAL mem = GlobalAlloc(GPTR, 1024); LPWORD lpw = (LPWORD)mem; lpw = CreateDlg(lpw, "Test", DS_SETFONT | DS_CENTER | WS_POPUP | WS_BORDER | WS_MINIMIZEBOX | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION, 0, 0, 249, 89, 0, 0, 3); // Création de quelques controles lpw = CreateControl(lpw, 0, "Button", "Cancel", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 192, 68, 50, 14, 1000); lpw = CreateControl(lpw, 0, "msctls_progress32", 0, WS_VISIBLE | WS_CHILD | PBS_SMOOTH, 7, 40, 235, 9, 1001); lpw = CreateControl(lpw, WS_EX_CLIENTEDGE, "edit", 0, WS_VISIBLE | WS_CHILD, 7, 7, 100, 13, 1002); DialogBoxIndirect(0, (LPDLGTEMPLATE)mem, NULL, DialogProc); GlobalFree(mem); #ifdef _DEBUG return 0; #else ExitProcess(0); #endif }

Codes Sources

Ajouter un commentaire Commentaires
Messages postés
1243
Date d'inscription
jeudi 31 mars 2005
Statut
Membre
Dernière intervention
3 août 2016
2
Merci bien pour l'explication :D
Messages postés
6535
Date d'inscription
lundi 16 décembre 2002
Statut
Membre
Dernière intervention
22 août 2010
10
Dans MSDN c'est écrit que les DLGITEMTEMPLATES doivent être alignées sur des DWORD (Each DLGITEMTEMPLATE structure in the template must be aligned on a DWORD boundary).
Or le premier param est aligné sur un WORD, mais pas forcément un DWORD
Si tu me demandes ce que signifie aligné sur un DWORD, ca veut juste dire que l'adresse est un mutliple de la taille d'un DWORD, soit 4
Donc, si (lpw & 3) est différent de 0, ca veut dire que c'est pas un multiple de 4 (les multiples de 4 on leur deux bits de poids faible à 0). Dans ce cas je l'incrémente (ce qui ajoute en fait deux au pointeur, qui est maintenant aligné sur un DWORD).
Messages postés
1243
Date d'inscription
jeudi 31 mars 2005
Statut
Membre
Dernière intervention
3 août 2016
2
Yop vecchio, j'ai regardé ton utilisation de DLGITEMTEMPLATE ca ressemble fort a DLGTEMPLATE mais je ne comprend pas cece :
if((LPARAM)lpw & 3) lpw++; // Aligner sur un DWORD

A quoi cella sert-il (et ne me dit pas a aligner sur un DWORD mdr :) ).
Messages postés
1910
Date d'inscription
vendredi 18 juin 2004
Statut
Modérateur
Dernière intervention
14 novembre 2014
13
Dommage que les fenêtres ne supportent pas cette méthode. On est obligés de passer par CreateWindow().
Messages postés
1910
Date d'inscription
vendredi 18 juin 2004
Statut
Modérateur
Dernière intervention
14 novembre 2014
13
Merci por ces précisions.
Pour modifier la police de tous les controles enfants, une simple petite boucle do while() suffit. J'ai utilisé cette astuce dans mes dernières sources déposées sur le site. Mais ta solution doit être meilleure car plus rapide.
C'est vrai que CreateWindow() travaille en pixels. Je contourne le problème dans une DialogBox en récupérant le clientrect(qui est en pixels) de la boite de dialogue et positionner les controles dans ce rectangle.
A propos de GetDlgItem(), si on utilise beaucoup les HWNDs, on peut les récupérer une seule fois pendant WM_INITDALOG. La boite s'affiche un peu moins vite mais c'est mieux que CreateWindow().
10/10
Afficher les 20 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.