Common Dialogs
O problema des intilnita in programare (nu numai in Visual Basic) este posibilitatea de a folosi dialogurile standard din Windows avind textele (caption-ul) butoanelor sau celorlalte controale modificate (in alta limba).
Aceasta problema am rezolvat-o pentru Delphi (vezi p01805 ) mult mai usor pentru ca in Delphi, controlul CommonDialog are evenimente (Show) pe cind in Visual Basic acesta nu are evenimente.
O solutie ar putea fi construirea unei forme utilizator care arata la fel si executa acelasi lucruri, insa asta inseamna redescoperirea rotii si oricum, este destul de greu de facut.
Solutia problemei consta in crearea dialogurilor utilizind functiile API Windows si subclasificarea acestora. Dialogurile standard se gasesc in 2 fisiere: comdlg32.ocx si comdlg32.dll. Pt. construirea la run-time a dialogurilor se folosesc functiile API din comdlg32.dll: GetOpenFileName, GetSaveFileName, ChooseFont, ChooseColor, respectiv Print care nu mai au nevoie de comdlg32.ocx.
Pentru fiecare din aceste dialoguri trebuie completata o structura (tip de date definit de utilizator) si apelata functia corespunzatoare. Unul din elementele structurii este adresa unei functii pentru tratarea mesajelor corespunzatoare dialogului. In aceasta functie vom trata mesajul WM_INITDIALOG care se primeste evident la initializarea dialogului si in care putem schimba textul dorit. In mod normal functia de afisare a dialogului returneaza 0 daca a totul decurge normal sau nenula daca a aparut o eroare (s-a apasat Cancel, s-a inchis pur si simplu dialogul sau alte erori). Aceasta valoare poate fi analizata prin apelarea functiei CommDlgExtendedError.
Sa analizam o problema care apare la toate dialogurile. Asa cum am mai spus, unul din elementele structurii este adresa unei functii care trateaza mesajele dialogului. Desi in Visual Basic exista AddressOf care returneaza adresa unei functii sau proceduri aceasta poate fi folosita doar in apelarea unor alte functii sau proceduri nu se poate folosi de sine statator. Deci, nu se poate scrie d.lpfnHook = AddressOf OProcedura si nici combinatii de acest gen. Pentru aceasta atribuire vom scrie d.lpfnHook = pAddressOf(addressOf OProcedura) unde functia pAddressOf este ca mai jos:
Public Function pAddressOf(ByVal procaddr As Long) As Long
pAddressOf = procaddr
End Function
In mod normal toate aceste dialoguri nu au in coltul stinga sus nici un icon. Pentru a afisa un icon folosim functia SendMessage cu mesajul WM_SETICON care are wParam nul (0&), iar lParam este un pointer la un icon (la iconul ferestrei).
Alta problema care apare este faptul ca functia care trateaza mesajele dialogului (functia 'Hook') trebuie pusa intr-un modul stantard (nu poate fi intr-o forma sau class-module).
Sa luam pe rind fiecare dialog.
1. Open - acesta se foloseste pentru selectarea sau crearea unui fisier dintr-un folder care poate fi creat. Acest dialog poate arata in 2 feluri diferite: asemanator cu dialogul open pt. Windows 3.x sau asemanator cu Windows Explorerul din Windows 9x. De asemenea poate fi sau nu subclasificat. Sa vedem mai jos codul pt. crearea unui dialog open cu textul in romaneste folosind functia GetOpenfileName.
Intr-un modul scriem functia de tratarea mesajelor (care modifica textul) astfel:
Private Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function SetDlgItemText Lib "user32" Alias "SetDlgItemTextA" _
(ByVal hDlg As Long, ByVal nIDDlgItem As Long, ByVal lpString As String) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Any) As Long
Public Const OFN_EXPLORER = &H80000
Public Const OFN_ENABLEHOOK = &H20
Private Const WM_INITDIALOG = &H110
Private Const WM_SETICON = &H80
Private Const IDC_OK As Long = 1
Private Const IDC_CANCEL As Long = 2
Private Const IDC_HELP As Long = 1038
Private Const IDC_READONLY As Long = 1040
Private Const IDC_LOOKIN As Long = 1091
Private Const IDC_FILESTYPES As Long = 1089
Private Const IDC_FILENAME As Long = 1090
Public Function fDialogCallBack(ByVal lnghwnd As Long, ByVal lngMessage As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Dim l As Long
If lngMessage = WM_INITDIALOG Then
If Form1.FLAGS And OFN_EXPLORER Then
l = GetParent(lnghwnd)
Else
l = lnghwnd
End If
SetDlgItemText l, IDC_OK, "&Deschide"
SetDlgItemText l, IDC_CANCEL, "Renunta"
SetDlgItemText l, IDC_LOOKIN, "Deschide &in"
SetDlgItemText l, IDC_FILENAME, "&Nume fisier"
SetDlgItemText l, IDC_FILESTYPES, "&Tip fisier"
SetDlgItemText l, IDC_READONLY, "Deschide &read-only"
SendMessage l, WM_SETICON, 0&, CLng(Form1.Icon)
End If
End Function
Pun pe o forma un buton (command1) si un text-box (text1) apoi se scrie:
Private Declare Function GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameA" _
(pOpenfilename As OPENFILENAME) As Long
Private Type OPENFILENAME
lStructSize As Long
hwndowner As Long
hInstance As Long
lpstrFilter As String
lpstrCustomFilter As String
nMaxCustFilter As Long
nFilterIndex As Long
lpstrFile As String
nMaxFile As Long
lpstrFileTitle As String
nMaxFileTitle As Long
lpstrInitialDir As String
lpstrTitle As String
FLAGS As Long
nFileOffset As Integer
nFileExtension As Integer
lpstrDefExt As String
lCustData As Long
lpfnHook As Long
lpTemplateName As String
End Type
Dim d As OPENFILENAME
Dim nf As String * 260 'numele de fisier selectat
Public FLAGS As Long
Private Sub Command1_Click()
d.lStructSize = Len(d)
d.hwndowner = hwnd 'HWND-ul parintelui dialogului
d.lpstrFilter = "Toate fisierele (*.*)" & Chr(0) & "*.*" & Chr(0) & _
"Fisiere text (*.txt)" & Chr(0) & "*.*" & Chr(0) & Chr(0)
d.lpstrCustomFilter = vbNullString
d.nFilterIndex = 1
d.lpstrFile = nf
d.nMaxFile = 260
d.lpstrTitle = "Un titlu" 'titlul dialogului
d.FLAGS = OFN_ENABLEHOOK Or OFN_EXPLORER
FLAGS = d.FLAGS
'adresa functiei de tratarea mesajelor dialogului
d.lpfnHook = pAddressOf(AddressOf fDialogCallBack)
GetOpenFileName d 'afiseaza dialogul
Text1 = d.lpstrFile 'foloseste numele selectat in dialog
End Sub
Felul in care arata dialogul este dat de valoarea continuta in cimpul FLAGS din tipul OPENFILENAME (pastrat si in variabila publica FLAGS din forma). Printre altele aceasta poate fi OFN_ENABLEHOOK pt. a activa utilizarea unei functii de tratarea mesajelor pentru dialog sau OFN_EXPLORER pt. stil gen Windows Explorer. In cazul in care stilul nu este OFN_EXPLORER atunci HWND-ul pasat functiei de tratarea mesajelor dialogului este chiar HWND-ul dialogului, altfel, daca stilul este OFN_EXPLORER atunci HWND-ul dialogului este GetParent-ul parametrului transmis.
Filter-ul dialogului este despartit prin chr(0), iar finalul este marcat prin chr(0) & chr(0).
Textul butoanelor si controalelor se poate schimba cu SetDlgItemText. Pt. asta trebuie sa stim identificatorul controlului in dialog. Pt. a determina identificatorii controalelor din dialog se poate folosi:
Dim l As Long
Dim sx As String * 260
Public Function fDialogCallBack(ByVal lnghwnd As Long, ByVal lngMessage As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
If lngMessage = WM_INITDIALOG Then
For i = 1 To 10000
sx = Space$(260)
l = GetDlgItemText(GetParent(lnghwnd), i, sx, 260)
'l = GetDlgItemText(lnghwnd, i, sx, 260) 'daca stilul nu este OFN_EXPLORER
If l <> 0 Then Debug.Print i & "--" & sx
Next
End If
End Function
Am presupus ca acesti identificatori sint intre 1 si 10000 ceea ce a fost adevarat. Acesti identificatori nu se schimba (ca HWND-ul). Asa am obtinut valorile constantelor IDC_.
In final fisierul selectat este in d.lpstrFile care este vid daca nu s-a selectat nimic.
Acesta este cel mai simplist mod de a folosi dialogul open subclasificat dar evident se pot face mult mai multe.
La toate aceste schimbari de texte din dialog puteti observa ca desi initial butonul Open are litera "O" subliniata (pt. utilizare cu ALT+O) daca se scrie &Deschide atunci litera "D" va fi subliniata si functioneaza in continuare cu ALT+D asemanator cum a functionat cu ALT+O.
2. Save, Save As... - aceste 2 dialoguri arata aproape la fel si au aproape acelasi comportament cu dialogul open. La fel exista 2 feluri diferite in care pot fi afisate dialogurile. Singurele diferente constau in functia care trebuie apelata, de aceasta data apelindu-se functia GetSaveFileName si faptul ca pe buton scrie Save nu Open. Insa, la fel trebuie completata o structura (tip) OPENFILENAME cu acelasi fel de valori. Nu ne vom in alte detalii la acest dialog chiar pentru ca este la fel ca la dialogul open.
3. Color - pentru afisarea acestui dialog la fel ca mai sus, se completeaza o structura (tip) CHOOSECOLOR, iar apoi se apeleaza functia API ChooseColor. Simplu!
Sa vedem mai intii codul dupa care o sa-l analizam. Punem intr-un modul:
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, _
ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Any) As Long
Private Declare Function SetDlgItemText Lib "user32" Alias "SetDlgItemTextA" _
(ByVal hDlg As Long, ByVal nIDDlgItem As Long, ByVal lpString As String) As Long
Private Const GW_CHILD = 5
Private Const GW_HWNDNEXT = 2
Private Const WM_INITDIALOG = &H110
Private Const WM_SETICON = &H80
Private Const WM_SETTEXT = &HC
Private Const IDC_CANCEL As Long = 2
Private Const IDC_ADDCUSTOMCOLORS As Long = 712
Private Const IDC_DEFINECUSTOMCOLORS As Long = 719
Private Const IDC_RED As Long = 726
Private Const IDC_GREEN As Long = 727
Private Const IDC_BLUE As Long = 728
Private Const IDC_HELP As Long = 1038
Private Const IDC_BASICCOLORS As Long = 65535
Public Function fColorCallBack(ByVal lnghwnd As Long, ByVal lngMessage As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Dim l as Long
If lngMessage = WM_INITDIALOG Then
SendMessage lnghwnd, WM_SETTEXT, 0&, "Selectie culori..."
SendMessage lnghwnd, WM_SETICON, 0&, CLng(frmColor.Icon)
SetDlgItemText lnghwnd, IDC_CANCEL, "Renunta"
SetDlgItemText lnghwnd, IDC_DEFINECUSTOMCOLORS, "&Defineste culori utilizator"
SetDlgItemText lnghwnd, IDC_ADDCUSTOMCOLORS, "&Adauga culori utilizator"
SetDlgItemText lnghwnd, IDC_RED, "&Rosu"
SetDlgItemText lnghwnd, IDC_GREEN, "&Verde"
SetDlgItemText lnghwnd, IDC_BLUE, "Albastr&u"
SetDlgItemText lnghwnd, IDC_HELP, "A&jutor"
SetDlgItemText lnghwnd, IDC_BASICCOLORS, "Culori de &baza"
l = GetWindow(lnghwnd, GW_CHILD)
l = GetWindow(l, GW_HWNDNEXT)
l = GetWindow(l, GW_HWNDNEXT)
SendMessage l, WM_SETTEXT, 0&, "&Culori utilizator"
End If
End Function
iar la forma cu un buton (command1) scriem:
Private Declare Function ChooseColor Lib "comdlg32.dll" Alias "ChooseColorA" _
(pChoosecolor As ChooseColor) As Long
Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, _
ByVal dwBytes As Long) As Long
Private Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)
Private Const GMEM_MOVEABLE = &H2
Private Const GMEM_ZEROINIT = &H40
Private Const GHND = (GMEM_MOVEABLE Or GMEM_ZEROINIT)
Private Const CC_ENABLEHOOK = &H10
Private Type ChooseColor
lStructSize As Long
hwndowner As Long
hInstance As Long
rgbResult As Long
lpCustColors As Long
FLAGS As Long
lCustData As Long
lpfnHook As Long
lpTemplateName As Long
End Type
Dim c As ChooseColor
Dim alCustomColors(15) As Long '16 elemente de la 0 la 15
Private Sub Command1_Click()
Dim l as Long
Dim lCustomColorSize As Long
Dim lCustomColorAddress As Long
Dim lMemHandle As Long
c.lStructSize = Len(c)
c.hwndowner = hwnd
lCustomColorSize = Len(alCustomColors(0)) * 16
lMemHandle = GlobalAlloc(GHND, lCustomColorSize)
If lMemHandle = 0 Then
Exit Sub
End If
lCustomColorAddress = GlobalLock(lMemHandle)
If lCustomColorAddress = 0 Then
Exit Sub
End If
Call CopyMemory(ByVal lCustomColorAddress, alCustomColors(0), lCustomColorSize)
c.lpCustColors = lCustomColorAddress
c.FLAGS = CC_ENABLEHOOK
c.lpfnHook = pAddressOf(AddressOf fColorCallBack)
l = ChooseColor(c)
if l<>0 then 'daca s-a selectat 'Cancel' sau nu a fost selectata o culoare atunci l=0
Call CopyMemory(alCustomColors(0), ByVal lCustomColorAddress, lCustomColorSize)
BackColor = c.rgbResult
End If
End Sub
Ceea ce difera la acest dialog fata de precedentele este faptul ca unul din elementele tipului CHOOSECOLOR este un pointer la un sir de 16 elemente in care vor fi returnate culorile utilizator alese, altele decit cele de baza. Dupa cum stiti Visual Basic-ul nu are pointeri asa ca trebuie sa apelam la subterfugii. Acestea sint functiile API GlobalAlloc, GlobalLock, GlobalFree si CopyMemory (care este de fapt RtlMoveMemory) cu care simulam pointerii. Codul programului cred ca este destul de lamuritor privind utilizarea acestor functii.
Pentru a activa subclasificarea dialogului in membrul FLAGS al structurii CHOOSECOLOR trebuie sa punem valoarea CC_ENABLEHOOK.
Dupa apelul functiei ChooseColor copiem valorile culorilor definite de utilizator inapoi in sirul alCustomColors pentru a pastra aceleasi valori data viitoare cind va fi afisat dialogul.
La acest dialog (ca si la urmatorul font) structura (tipul) cu care se apeleaza functia API corespunzatoare nu are nici un membru pentru a modifica numele dialogului. Pentru a modifica numele dialogului se apeleaza SendMessage cu mesajul WM_SETTEXT (pt. HWND-ul ferestrei dialogului) cu wParam nul (0&) si lParam avind noul nume al dialogului.
In final, rezultatul alegerii dvs. se regaseste in rgbColor.
4. Font - acest dialog este foarte asemanator cu dialogul color si asa cum banuiti se apeleaza pentru afisarea lui functia API Windows ChooseFont cu o structura de tip CHOOSEFONT. Sa vedem mai intii codul din modul:
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _
ByVal lParam As Any) As Long
Private Declare Function SetDlgItemText Lib "user32" Alias "SetDlgItemTextA" _
(ByVal hDlg As Long, ByVal nIDDlgItem As Long, ByVal lpString As String) As Long
Private Const WM_INITDIALOG = &H110
Private Const WM_SETTEXT = &HC
Private Const WM_SETICON = &H80
Private Const IDC_OK As Long = 1
Private Const IDC_CANCEL As Long = 2
Private Const IDC_HELP As Long = 1038
Private Const IDC_APPLY As Long = 1026
Private Const IDC_STRIKEOUT As Long = 1040
Private Const IDC_UNDERLINE As Long = 1041
Private Const IDC_EFFECTS As Long = 1072
Private Const IDC_SAMPLE As Long = 1073
Private Const IDC_FONT As Long = 1088
Private Const IDC_FONTSTYLE As Long = 1089
Private Const IDC_SIZE As Long = 1090
Private Const IDC_COLOR As Long = 1091
Public Function pAddressOf(ByVal procaddr As Long) As Long
pAddressOf = procaddr
End Function
Public Function fFontCallBack(ByVal lnghwnd As Long, ByVal lngMessage As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Dim l As Long
If lngMessage = WM_INITDIALOG Then
SendMessage lnghwnd, WM_SETTEXT, 0&, "Selectie fonturi"
SendMessage lnghwnd, WM_SETICON, 0&, CLng(Form2.Icon)
SetDlgItemText lnghwnd, IDC_CANCEL, "Renunta"
SetDlgItemText lnghwnd, IDC_STRIKEOUT, "&Taiat"
SetDlgItemText lnghwnd, IDC_UNDERLINE, "S&ubliniat"
SetDlgItemText lnghwnd, IDC_EFFECTS, "Efecte"
SetDlgItemText lnghwnd, IDC_FONTSTYLE, "&Stilul fontului"
SetDlgItemText lnghwnd, IDC_SIZE, "&Marime"
SetDlgItemText lnghwnd, IDC_SAMPLE, "Exemplu"
End If
End Function
iar intr-o forma cu un buton (command1) si un text-box (text1) scriem:
Private Declare Function CHOOSEFONT Lib "comdlg32.dll" Alias "ChooseFontA" _
(pChoosefont As CHOOSEFONT) As Long
Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, _
ByVal dwBytes As Long) As Long
Private Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)
Private Declare Function GetDeviceCaps& Lib "gdi32" (ByVal hdc&, ByVal nIndex&)
'constants for API memory functions
Private Const GMEM_MOVEABLE = &H2
Private Const GMEM_ZEROINIT = &H40
Private Const GHND = (GMEM_MOVEABLE Or GMEM_ZEROINIT)
Private Const cdlCFBoth = &H3&
Private Const cdlCFScreenFonts = &H1&
Private Const cdlCFTTOnly = &H40000
Private Const cdlCFEnableHook = &H8&
Private Const LF_FACESIZE = 32
Private Const FW_BOLD = 700
Private Type LOGFONT
lfHeight As Long
lfWidth As Long
lfEscapement As Long
lfOrientation As Long
lfWeight As Long
lfItalic As Byte
lfUnderline As Byte
lfStrikeOut As Byte
lfCharSet As Byte
lfOutPrecision As Byte
lfClipPrecision As Byte
lfQuality As Byte
lfPitchAndFamily As Byte
'lfFaceName(LF_FACESIZE) As Byte
lfFaceName As String * LF_FACESIZE
End Type
Private Type CHOOSEFONT
lStructSize As Long
hwndowner As Long
hdc As Long
lpLogFont As Long
iPointSize As Long
FLAGS As Long
rgbColors As Long
lCustData As Long
lpfnHook As Long
lpTemplateName As String
hInstance As Long
lpszStyle As String
nFontType As Integer
MISSING_ALIGNMENT As Integer
nSizeMin As Long
nSizeMax As Long
End Type
Private Sub Command1_Click()
Dim df As CHOOSEFONT
Dim f As LOGFONT
Dim l As Long
Dim lLogFontSize As Long
Dim lMemHandle As Long
Dim lLogFontAddress As Long
f.lfHeight = Text1.Font.Size / (72 / GetDeviceCaps(hdc, 90)) * -1
f.lfFaceName = Text1.FontName & Chr(0)
f.lfItalic = IIf(Text1.FontItalic, 1, 0)
f.lfUnderline = IIf(Text1.FontUnderline, 1, 0)
f.lfStrikeOut = IIf(Text1.FontStrikethru, 1, 0)
f.lfWeight = IIf(Text1.FontBold, FW_BOLD, 0)
lLogFontSize = Len(f)
lMemHandle = GlobalAlloc(GHND, lLogFontSize)
If lMemHandle = 0 Then
Exit Sub
End If
lLogFontAddress = GlobalLock(lMemHandle)
If lLogFontAddress = 0 Then
Exit Sub
End If
Call CopyMemory(ByVal lLogFontAddress, f, lLogFontSize)
df.rgbColors = Text1.ForeColor
df.lpLogFont = lLogFontAddress
df.FLAGS = cdlCFScreenFonts Or &H100& Or &H40& Or cdlCFEnableHook 'Or cdlCFTTOnly
df.lpfnHook = pAddressOf(AddressOf fFontCallBack)
df.lStructSize = Len(df)
df.hwndowner = hwnd
l = CHOOSEFONT(df)
If l <> 0 Then
Call CopyMemory(f, ByVal lLogFontAddress, lLogFontSize)
Text1.FontName = f.lfFaceName
Text1.FontSize = CLng(df.iPointSize / 10)
Text1.FontBold = (f.lfWeight >= FW_BOLD)
Text1.FontItalic = (f.lfItalic = 1)
Text1.FontStrikethru = (f.lfStrikeOut = 1)
Text1.FontUnderline = (f.lfUnderline = 1)
Text1.ForeColor = df.rgbColors
End If
End Sub
Si la acest dialog se folosesc pointerii pt. ca unul din elemetele structurii CHOOSEFONT este un pointer la structura LOGFONT asa incit avem nevoie de functiile API GlobalAlloc, GlobalLock, GlobalFree si CopyMemory. Mai intii completam structura (tipul) LOGFONT cu datele fontului selectat la aparitia dialogului iar apoi completam elemetele structurii CHOOSEFONT.
De asemenea, pentru a activa subclasificarea dialogului in membrul FLAGS al structurii CHOOSEFONT trebuie sa punem valoarea CF_ENABLEHOOK (cdlCFEnableHook). In acelasi loc se poate specifica si alte setari, de ex. daca sa afiseze sau nu toate fonturile sau doar cele TTF (cdlCFTTOnly).
Dupa apelul functiei ChooseFont valorile selectate sint copiate inapoi in structura (tipul) LOGFONT de unde sint folosite. Unele valori selectate se gasesc la structura CHOOSEFONT nu la LOGFONT.
5. Print, Print Setup - pentru a utiliza aceste dialoguri folosind functiile API PrintDlg se poate consulta Q173981 care prezinta un exemplu concret. Insa, acest exemplu nu subclasifica dialogul. Toate incercarile mele de a subclasifica acest dialog au fost nereusite asa ca nu-mi ramine decit sa va rog sa-mi trimite-ti si mie un exemplu de subclasificare al acestui dialog (tratind mesajul WM_INITDIALOG) daca a-ti reusit dvs. Multumesc in avans.
6. Help - desi la CommonDialog este metoda ShowHelp cu ajutorul caruia se poate afisa un fisier de help (*.hlp), acesta nu este de fapt un dialog propriu-zis si nu avem de ce sa-l subclasificam pentru a schimba caption-ul controalelor pentru ca nu are controale. Acelasi lucru se poate face si apelind functia API WinHelp fara utilizarea controlului dialog (si fara comdlg32.ocx) ca mai jos (nu avem nevoie de nici un modul):
Private Declare Function WinHelp Lib "user32" Alias "WinHelpA" (ByVal hwnd As Long, _
ByVal lpHelpFile As String, ByVal wCommand As Long, ByVal dwData As Long) As Long
Private Const HELP_COMMAND = &H102&
Private Const HELP_CONTENTS = &H3&
Private Const HELP_CONTEXT = &H1 ' Display topic in ulTopic
Private Const HELP_CONTEXTPOPUP = &H8&
Private Const HELP_FORCEFILE = &H9&
Private Const HELP_HELPONHELP = &H4 ' Display help on using help
Private Const HELP_INDEX = &H3 ' Display index
Private Const HELP_KEY = &H101 ' Display topic for keyword in offabData
Private Const HELP_MULTIKEY = &H201&
Private Const HELP_PARTIALKEY = &H105&
Private Const HELP_QUIT = &H2 ' Terminate help
Private Const HELP_SETCONTENTS = &H5&
Private Const HELP_SETINDEX = &H5 ' Set current Index for multi index help
Private Const HELP_SETWINPOS = &H203&
Private Sub Command1_Click()
WinHelp hwnd, "c:\cale\help.hlp", HELP_CONTENTS, 0&
End Sub
Acelasi lucru se obtinea punind un CommonDialog pe o forma si scriind:
Private Sub Command1_Click()
CommonDialog1.HelpFile = "c:\cale\help.hlp"
CommonDialog1.HelpCommand = cdlHelpContents
CommonDialog1.ShowHelp
End Sub
|