Affichage successifs par simple clic de divers fichiers texte ou d'immages dans des onglets différents.
Source / Exemple :
;Semainier.asm
.586
.model flat, stdcall
option casemap :none ; case sensitive
;*********************************************
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\comCtl32.inc
include \masm32\include\shell32.inc
include \masm32\include\gdi32.inc
include \masm32\include\masm32.inc
include \masm32\include\ole32.inc
include \masm32\include\oleaut32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\comCtl32.lib
includelib \masm32\lib\shell32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\ole32.lib
includelib \masm32\lib\oleaut32.lib
;********************************
; MACROS
;********************************
szText MACRO Name, Text:VARARG
LOCAL lbl
jmp lbl
Name db Text,0
lbl:
ENDM
m2m MACRO M1, M2
push M2
pop M1
ENDM
return MACRO arg
mov eax, arg
ret
ENDM
;**********************************
; PROTO
;***********************************
Ed1Proc3 PROTO :DWORD,:DWORD,:DWORD,:DWORD
Charge PROTO :DWORD,:DWORD
DlgProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
Child1Proc PROTO :DWORD,:DWORD,:DWORD,:DWORD
DlgProc1 PROTO :DWORD,:DWORD,:DWORD,:DWORD
PainProc PROTO :DWORD
.data
Titre db "Le bouton (en bas à gauche) va charger un nouveau texte.",13,10
db "Le texte prévu à l'origine ne sera affiché qu'a la prochaine sélection de l'onglet",0
Titre1 db "Le bouton du bas termine l'application. Si vous cliquez sur lui ..... Salut!!!",0
Titre2 db "Le bouton3 va charger le fichier source de cette application",0
Titre3 db "Voici le Copyright",0
lun db "Lundi",0
mar db "Mardi",0
mer db "Mercredi",0
jeu db "Jeudi",0
ven db "Vendredi",0
sam db "Samedi",0
dim db "Dimanche",0
Child1Name db "IDD_Child1",0
NomFic1 db "LisezMoi.txt",0
NomFic2 db "Semainier.rc",0
NomFic3 db "Semainier.asm",0
NomFic4 db "errR.txt",0
NomFic5 db "errL.txt",0
NomFic6 db "errC.txt",0
NomFic7 db "disasm.txt",0
Pas2Fic db "Le Fichier n'existe pas ou le chemin est incorrect.",0
;*************************************
.data?
hInstance dd ?
hEdit dd ?
Handles LABEL DWORD
hBtn1 dd ?
hBtn2 dd ?
hBtn3 dd ?
hBtn4 dd ?
hBtn5 dd ?
hBtn6 dd ?
hBtn7 dd ?
hBmp dd ?
hwndTab dd ?
TabIndex dd ?
Child1 dd ?
handle1 dd ?
hIcon dd ?
hFile dd ?
hMem dd ?
pMem dd ?
NbLus dd ?
TabCtrlItem TC_ITEM <?>
;*************************************
.const
IDD_DIALOG1 equ 101
IDC_TAB1 equ 1001
IDC_BTN1 equ 1002
IDC_BTN2 equ 1003
IDC_BTN3 equ 1004
IDC_BTN4 equ 1006
IDC_BTN5 equ 1007
IDC_BTN6 equ 1008
IDC_BTN7 equ 1009
;*********************************************
.code
;*********************************************
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke InitCommonControls
invoke DialogBoxParam,hInstance,101,NULL,Addr DlgProc,NULL
Sortie::
invoke ExitProcess,0
;*****************************************
DlgProc proc hWin :DWORD,uMsg :DWORD,wParam :DWORD, lParam :DWORD
.IF uMsg == WM_INITDIALOG
;**********************************************
; Récupérer le handle de TabControl
;**********************************************
invoke GetDlgItem,hWin,IDC_TAB1
mov hwndTab,eax
;**********************************************************************
; Placer le texte dans l'onglet et l'onglet dans TabControl
; ATTENTION : LES INDEX COMMENCENT TOUJOURS à Zéro !!
;**********************************************************************
mov TabCtrlItem.imask,TCIF_TEXT
mov TabCtrlItem.pszText,offset lun
invoke SendMessage,hwndTab,TCM_INSERTITEM,0,offset TabCtrlItem
;*************************************************
; Idem pour chaque jour de la semaine
;*************************************************
mov TabCtrlItem.imask,TCIF_TEXT
mov TabCtrlItem.pszText,offset mar
invoke SendMessage,hwndTab,TCM_INSERTITEM,1,offset TabCtrlItem
mov TabCtrlItem.imask,TCIF_TEXT
mov TabCtrlItem.pszText,offset mer
invoke SendMessage,hwndTab,TCM_INSERTITEM,2,offset TabCtrlItem
mov TabCtrlItem.imask,TCIF_TEXT
mov TabCtrlItem.pszText,offset jeu
invoke SendMessage,hwndTab,TCM_INSERTITEM,3,offset TabCtrlItem
mov TabCtrlItem.imask,TCIF_TEXT
mov TabCtrlItem.pszText,offset ven
invoke SendMessage,hwndTab,TCM_INSERTITEM,4,offset TabCtrlItem
mov TabCtrlItem.imask,TCIF_TEXT
mov TabCtrlItem.pszText,offset sam
invoke SendMessage,hwndTab,TCM_INSERTITEM,5,offset TabCtrlItem
mov TabCtrlItem.imask,TCIF_TEXT
mov TabCtrlItem.pszText,offset dim
invoke SendMessage,hwndTab,TCM_INSERTITEM,6,offset TabCtrlItem
;*****************************************************************
; Création des onglets et de la procédure rattachée
;*****************************************************************
invoke CreateDialogParam,hInstance,addr Child1Name,hwndTab,addr Child1Proc,0
mov Child1,eax
;********************************************
; Récupération des handles des boutons
;********************************************
invoke GetDlgItem,hWin,IDC_BTN1
mov hBtn1,eax
invoke GetDlgItem,hWin,IDC_BTN2
mov hBtn2,eax
invoke GetDlgItem,hWin,IDC_BTN3
mov hBtn3,eax
invoke GetDlgItem,hWin,IDC_BTN4
mov hBtn4,eax
invoke GetDlgItem,hWin,IDC_BTN5
mov hBtn5,eax
invoke GetDlgItem,hWin,IDC_BTN6
mov hBtn6,eax
invoke GetDlgItem,hWin,IDC_BTN7
mov hBtn7,eax
;*********************************************************
; Montrer le bouton1 et l'onglet1 et cacher tout le reste.
;*********************************************************
invoke ShowWindow,hBtn1,SW_SHOW
invoke UpdateWindow,hBtn1
invoke ShowWindow,hBtn2,SW_HIDE
invoke ShowWindow,hBtn3,SW_HIDE
invoke ShowWindow,hBtn4,SW_HIDE
invoke ShowWindow,hBtn5,SW_HIDE
invoke ShowWindow,hBtn6,SW_HIDE
invoke ShowWindow,hBtn7,SW_HIDE
INVOKE ShowWindow,Child1,SW_SHOWDEFAULT
.ELSEIF uMsg == WM_NOTIFY
.if wParam == IDC_TAB1;;; Si le message est émis par Tab :
mov eax,lParam;;; Récupérer le 2ème paramètre.
mov eax,(NMHDR ptr[eax]).code;;; Commande correspondante ==> eax
cmp eax,TCN_SELCHANGE ;;; On change ?
jz ChangeTab ;;; oui
jnz NeChangePas ;;; non
ChangeTab:
;***************************************************
; Récuperer l'adresse du bouton visible actuellement
; et le cacher,demander l'index de l'onglet qui vient
; d'être sélectionné.
;***************************************************
mov ebx,TabIndex
mov eax,[Handles+ebx*4]
invoke ShowWindow,eax,SW_HIDE
invoke SendMessage,hwndTab,TCM_GETCURSEL,0,0
mov TabIndex,eax
.if TabIndex == 0
;*****************************************************
; Et si c'est le 0 : mettre l'onglet en lecture seule,
; Charger le 1er fichier et montrer le bouton1.
; WINDOWS XP réclame le rafraichissement de l'onglet
; mais ne demande pas qu'il soit montré !!
;*****************************************************
invoke SendMessage,handle1,EM_SETREADONLY,TRUE,NULL
invoke Charge,addr NomFic4,handle1
invoke UpdateWindow,handle1
invoke ShowWindow,hBtn1,SW_SHOW
invoke UpdateWindow,hBtn1
;;; INVOKE ShowWindow,Child1,SW_SHOWDEFAULT
invoke UpdateWindow,Child1
;***************************************************************************************
; Même opération pour les suivants,le contenu de l'onglet sera chargé lors de sa
; sélection,il pourra être changé par le bouton correspondant et éventuellement,
; comme ci-dessus, revenir au 1er contenu chaque fois que l'onglet sera appelé.
;***************************************************************************************
.elseif TabIndex == 1
;*******************************************************************************
; Comme l'éditeur est identique pour tous les jours,si il a été mis en écriture,
; même une seule fois, il faut le remettre en lecture seule a chaque sélection.
; ici on affiche toujours le même message,puisque le bouton sert a quitter.
;*******************************************************************************
invoke SendMessage,handle1,EM_SETREADONLY,TRUE,NULL
invoke SendMessage,handle1,WM_SETTEXT,NULL,addr Titre1
invoke ShowWindow,hBtn2,SW_SHOW
invoke UpdateWindow,hBtn2
;;; INVOKE ShowWindow,Child1,SW_SHOWDEFAULT
invoke UpdateWindow,Child1
.elseif TabIndex == 2
invoke SendMessage,handle1,EM_SETREADONLY,TRUE,NULL
invoke Charge,addr NomFic2,handle1; ici retour a chaque changement.
invoke ShowWindow,hBtn3,SW_SHOW
invoke UpdateWindow,hBtn3
;;; INVOKE ShowWindow,Child1,SW_SHOWDEFAULT
invoke UpdateWindow,Child1
.elseif TabIndex == 3
invoke SendMessage,handle1,EM_SETREADONLY,TRUE,NULL
invoke Charge,addr NomFic1,handle1
invoke ShowWindow,hBtn4,SW_SHOW
invoke UpdateWindow,hBtn4
;;; INVOKE ShowWindow,Child1,SW_SHOWDEFAULT
invoke UpdateWindow,Child1
.elseif TabIndex == 4
invoke SendMessage,handle1,EM_SETREADONLY,TRUE,NULL
invoke Charge,addr NomFic3,handle1
invoke ShowWindow,hBtn5,SW_SHOW
invoke UpdateWindow,hBtn5
;;; INVOKE ShowWindow,Child1,SW_SHOWDEFAULT
invoke UpdateWindow,Child1
.elseif TabIndex == 5
;*************************************************************
; écriture possible ce jour là : FALSE
; V
;*************************************************************
invoke SendMessage,handle1,EM_SETREADONLY,FALSE,NULL
invoke Charge,addr NomFic6,handle1
invoke ShowWindow,hBtn6,SW_SHOW
invoke UpdateWindow,hBtn6
;;; INVOKE ShowWindow,Child1,SW_SHOWDEFAULT
invoke UpdateWindow,Child1
.elseif TabIndex == 6
invoke SendMessage,handle1,EM_SETREADONLY,TRUE,NULL
invoke ShowWindow,hBtn7,SW_SHOW
invoke UpdateWindow,hBtn7
invoke Charge,addr NomFic7,handle1
;;; INVOKE ShowWindow,Child1,SW_SHOWDEFAULT
invoke UpdateWindow,Child1
.endif
NeChangePas:
.endif
.ELSEIF uMsg == WM_COMMAND
mov eax,wParam
mov edx,eax
shr edx,16
and eax,0FFFFh
.if edx == BN_CLICKED
.if eax == IDC_BTN1
invoke Charge,addr NomFic3,handle1; change le contenu de l'onglet1.
invoke UpdateWindow,Child1
ret
.elseif eax == IDC_BTN2
invoke EndDialog,hWin,0 ; ici on fout le camp !!.
.elseif eax == IDC_BTN3
invoke Charge,addr NomFic7,handle1; et la, on change, tout est possible.
invoke UpdateWindow,Child1
ret
.elseif eax == IDC_BTN4;; et ici on ne fait rien.
;*********************************************
; créer la boite de dialogue pour copyright.
; et rafraichir l'affichage précédent lorsque
; l'on quitte le copyright.
;*********************************************
invoke DialogBoxParam,hInstance,9,NULL,addr DlgProc1,NULL
invoke UpdateWindow,Child1
ret
.elseif eax == IDC_BTN5;;
invoke Charge,addr NomFic2,handle1
invoke UpdateWindow,Child1
.elseif eax == IDC_BTN6;; on remet en lecture seule.
invoke SendMessage,handle1,EM_SETREADONLY,TRUE,NULL
invoke Charge,addr NomFic5,handle1
invoke UpdateWindow,Child1
.elseif eax == IDC_BTN7;;
invoke Charge,addr NomFic1,handle1
invoke UpdateWindow,Child1
.endif
.endif
.ELSEIF uMsg == WM_CLOSE
invoke EndDialog,hWin,0
.ELSE
mov eax,FALSE
ret
.ENDIF
mov eax,TRUE
ret
DlgProc endp
;******************************************
Child1Proc proc hWnd1 :DWORD,uMsg :DWORD,wParam :DWORD,lPARAM :DWORD
.IF uMsg == WM_INITDIALOG
;********************************
; on cherche le handle de l'édit.
;********************************
invoke GetDlgItem,hWnd1,3615
mov handle1,eax
;*******************************************************************************
; Mise de l'onglet en lecture seule. (pas obligatoire,chacun fait ce qu'il veut)
;*******************************************************************************
invoke SendMessage,handle1,EM_SETREADONLY,TRUE,NULL
;***********************************************************************************
; Chargement du contenu original : invoke Charge,addr NomFic4,handle1 ou alors
; on peut y inscrire un message: Il va remplacer le contenu précédent qui ne sera vu
; qu'a la 2ème sélection de l'onglet.
;***********************************************************************************
invoke SendMessage,handle1,WM_SETTEXT,NULL,addr Titre
.ENDIF
ret
Child1Proc endp
;*****************************************
Charge proc Nom :DWORD,Editeur :DWORD
invoke CreateFile,Nom,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,
FILE_ATTRIBUTE_ARCHIVE,NULL
.IF eax == INVALID_HANDLE_VALUE
invoke SendMessage,Editeur,WM_SETTEXT,NULL,addr Pas2Fic
.ELSE
mov hFile,eax
invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,65535
mov hMem,eax
invoke GlobalLock,hMem
mov pMem,eax
invoke ReadFile,hFile,pMem,65534,addr NbLus,NULL
invoke SendMessage,Editeur,WM_SETTEXT,NULL,pMem
invoke CloseHandle,hFile
invoke GlobalUnlock,pMem
invoke GlobalFree,hMem
.ENDIF
ret
Charge endp
;*****************************************
DlgProc1 proc hWnd3 :DWORD,uMsg :DWORD,wParam :DWORD,lParam :DWORD
.IF uMsg == WM_INITDIALOG
;***********************************************************************************
; Placer l'icone (Information) dans la barre de titre du controle de Copyright,
; Créer le bouton qui supportera l'image,charger l'image et la placer sur le bouton.
;***********************************************************************************
invoke LoadIcon,NULL,IDI_ASTERISK
invoke SendMessage,hWnd3,WM_SETICON,1,eax
invoke SetWindowText,hWnd3,addr Titre3
;**************************************************
; Pour un Bitmap : utilise IconButton, pas PainProc
;**************************************************
; invoke IconButton,hWnd3,0,0,330,210,400
; invoke LoadBitmap,hInstance,10
; invoke SendMessage,hBtn,BM_SETIMAGE,0,eax
;************************************************
; Pour un .JPG : utilise PainProc, pas IconButton
;************************************************
invoke BitmapFromResource,hInstance,2000
mov hBmp,eax
.ELSEIF uMsg == WM_PAINT
invoke PainProc,hWnd3
.ELSEIF uMsg == WM_COMMAND
.if wParam == IDCANCEL
invoke EndDialog,hWnd3,0
.endif
.ELSEIF uMsg == WM_CLOSE
invoke EndDialog,hWnd3,0
.ENDIF
xor eax,eax
ret
DlgProc1 endp
;*****************************************
;
;******************************************
;Procédure utilisée si il s'agit d'un .JPG
;******************************************
PainProc proc hWnd3 :DWORD
LOCAL hDC:DWORD,hOld :DWORD
LOCAL memDC :DWORD,ps :PAINTSTRUCT
invoke BeginPaint,hWnd3,addr ps
mov hDC,eax
invoke CreateCompatibleDC,hDC
mov memDC,eax
invoke SelectObject,memDC,hBmp
mov hOld,eax
invoke BitBlt,hDC,4,4,320,200,memDC,0,0,SRCCOPY
invoke SelectObject,hDC,hOld
invoke DeleteDC,memDC
invoke EndPaint,hWnd3,addr ps
ret
PainProc endp
;*****************************************
;*****************************************
end start
;******************************************
; Semainier.rc
#include "\masm32\include\resource.h"
#define IDD_DIALOG1 101
#define IDC_TAB1 1001
#define IDC_BTN1 1002
#define IDC_BTN2 1003
#define IDC_BTN3 1004
#define IDC_BTN4 1006
#define IDC_BTN5 1007
#define IDC_BTN6 1008
#define IDC_BTN7 1009
#define IDC_EDT1 1005
500 ICON DISCARDABLE "icone29.ico"
;**********************************************************************************;
; ATTENTION : tout changement de fonte (taille ou type) dans un des deux controles ;
; entraine une modification des dimensions de la table. ;
;**********************************************************************************;
IDD_DIALOG1 DIALOGEX 0,0,340,250
;;;;;;;;;;;;; RSRC.rc de essai.29;;;;;;;;;;;;;;
STYLE DS_CENTER | WS_SYSMENU | WS_VISIBLE |WS_CAPTION | WS_MINIMIZEBOX | WS_OVERLAPPED
CAPTION "Tab Control"
FONT 10,"Courier new",0,0
BEGIN
CONTROL "",IDC_TAB1,"SysTabControl32",NOT 0x00820000 | 0x50018000,6,1,325,231,0x00000000
PUSHBUTTON "Change-L",IDC_BTN1,6,234,50,15,0, ,0
PUSHBUTTON "&Quitte",IDC_BTN2,51,234,50,15,0, ,0
PUSHBUTTON "Change-Me",IDC_BTN3,96,234,50,15, ,0
PUSHBUTTON "Copyright",IDC_BTN4,141,234,50,15,0, ,0
PUSHBUTTON "Change-V",IDC_BTN5,186,234,50,15,0, ,0
PUSHBUTTON "Change-S",IDC_BTN6,231,234,50,15,0, ,0
PUSHBUTTON "Change-D",IDC_BTN7,278,234,50,15,0, ,0
END
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
IDD_CHILD1 DIALOG 2,15,322,266
STYLE WS_CHILD
FONT 10, "Courier"
{
EDITTEXT 3615,2,2,316,261,WS_BORDER | WS_GROUP | WS_VSCROLL | ES_MULTILINE
}
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
; 10 BITMAP MOVEABLE PURE LOADONCALL DISCARDABLE "\essai28.bmp"
2000 IMAGE DISCARDABLE "bd015.jpg"
9 DIALOGEX MOVEABLE IMPURE LOADONCALL DISCARDABLE 50,50,165,185
STYLE DS_CENTER | WS_SYSMENU | WS_OVERLAPPED |WS_VISIBLE |WS_CAPTION | DS_MODALFRAME | DS_3DLOOK
CAPTION " "
FONT 10,"Courier new",0,1
BEGIN
CTEXT "Copyright © 2004\nJe sais,ça date un peu,mais\nje l'avais oublié dans un coin de l'ordinateur\net je viens de le retrouver et de le compléter.",0,10,105,140,70
PUSHBUTTON "Quitte",IDCANCEL,58,170,50,13,0, ,0
END
;
;«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»
Conclusion :
Simple amusement qui pourrait tout de même être utile à certains.
Par exemple pour afficher le menu de la semaine ou encore un emploi du temps.
Le nombre d'onglets n'est limité que par la surface d'écran dont on dispose.
A partir de ce projet élémentaire diverses variations sont possibles.
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.