3 |
CommonDialog |
Potřebuji dát uživateli na výběr font. Chtěl jsem pro to použít CommonDialog, ale
po spuštění metody ShowFont mi vyskočí okno s chybou "Nejsou nainstalována
žádná písma ...", což je samozřejmně nesmysl. |
Před zobrazením okna s fonty musíte vždy nastavit vlastnost Flags a to na ty
fonty, které chcete používat. Jestli pro tiskárnu, obrazovku nebo obojí, tzn. cdlCFPrinterFonts,
cdlCFScreenFonts nebo cdlCFBoth. Fonty, které umí obrazovka, totiž ne vždy
umí i tiskárna, speciální případ je např. Obecná nebo textová tiskárna, ta umí pouze jeden font. |
|
1/2000 |
3 |
Registr Windows |
Můžete mi prosím poradit, jak zapisovat položky do registru v systému Windows 95. |
Visual Basic má čtyři funkce pro práci s registrem. GetSetting čte hodnoty z registru,
GetAllSettings stejně tak, ale více hodnot naráz, DeleteSetting maže hodnoty a SaveSetting
ukládá. Tyto funkce však neumožňují vybrat větev v registru, kam chcete hodnoty uložit. Vždy ukládají
do HKEY_CURRENT_USER\Software\VB and VBA Program Settings. Pokud chcete pracovat s registrem více,
musíte použít API funkce. Pokud je budete chtít použít, zkopírujte si modul,
který vám pro začátek pomůže. Obsahuje několik funkcí pro práci s registrem. Přesný popis a použití API pro registr najdete v MSDN. |
Zkuste/VBasic/CCD/Otazky/basreg.ccd |
1/2000 |
3 |
MDI formulář |
Vytvářím aplikaci s MDI oknem. Po nějaké události, např. zrušení MDI formuláře, potřebuji zrušit všechna child okna.
Můžete mi poradit, jak na to? |
Ke zrušení všech child formulářů je nejlepší použít kolekci Forms. Při procházení jejich prvků jednoduše
kontrolujete, zda mají vlastnost MDIChild nastavenou na hodnotu True. Pokud ano, jsou uvolněny
z paměti. Např.
Dim frm As Form
For Each frm In Forms
If frm.Name <> "nazevMDIformulare" Then
If frm.MDIChild Then Unload frm
End If
Next frm
|
|
1/2000 |
3 |
System Tray |
Jak lze přidat ikonu do oblasti vpravo dole do Windows, kde je zobrazený čas, hlasitost ... |
Oblast o které mluvíte, se jmenuje System Tray a ikonu, tedy spuštěný program, do ní přidává
API funkce Shell_NotifyIcon. Její použití je vcelku jednoduché, horší je to už
s obsluhou menu. Proto opět malý příklad. |
Zkuste/VBasic/CCD/Otazky/tray.ccd |
1/2000 |
3 |
Nápověda |
Nevíte, jak vytvořit nápovědu k menu tak, že když najedu na nějakou položku, např.
ve StatusBaru se mi objeví její popis? Stejně to funguje např. v Office. |
Protože odpověď pro tuto otázku je poněkud obsáhlejší, vypomůžeme si opět příkladem.
V podstatě jde o to, zachytit zprávu WM_SELECT pomocí API funkce SetWindowsLong, vyhledat, které menu je právě
vybráno a zobrazit zprávu. |
Zkuste/VBasic/CCD/Otazky/helpmenu.ccd |
2/2000 |
3 |
ListView |
Potřebuji v ListView zvýraznit některé položky tučně. Stejně jako je to např. v aplikaci Outlook Express, když je některá
pošta nepřečtená. |
Položka, tedy řádek, v ListView je charakterizována objektem ListItem kolekce
ListItems. Pokud je potřeba mít některou tučně, stačí nastavit její vlastnost
Bold = True. Např. takto:
Dim lstPol As ListItem
Set lstPol = ListView1.Add(Text:="Prvni") 'nova polozka v ListView
lstPol.Bold = True
|
|
2/2000 |
3 |
Tisk |
Už nějakou dobu se snažím poslat v programu vytvořeném ve VB 5.0 informace k vytisknutí na
jinou než výchozí tiskárnu. Vždy se mi podaří nastavení změnit jen na chvíli a to do doby,
než změním font tisku nebo odešlu něco na tisk. Potom se hned nastaví opět výchozí tiskárna. Např.:
MsgBox(printer.devicename) 'Nastavená výchozí tiskárna 2
Set Printer = Printers(3) 'Nastavení tisku na tiskárnu 3
MsgBox(printer.devicename) 'Nastavená tiskárna 3
Printer.Print "Text" 'Tento text se už tiskne na výchozí tiskárnu 2
MsgBox(printer.devicename) 'A zde je nastavená výchozí tiskárna 2
|
Tento příklad jsem zkoušel na svém počítači a fungovalo to bez problémů. Buď je chyba
někde ve zbytku kódu nebo zkuste místo použití objektu Printer deklarovat proměnnou typu Printer a tu potom používat. |
|
2/2000 |
3 |
Spuštění programu po startu |
Jak při instalaci (či jinak elegantně) zařídit, aby se program spouštěl automaticky po startu počítače?
Je určen pro SysTray oblast. |
Jak pozměnit standardní instalační program dodávaný s VB najdete v dnešních zdrojových kódech. Nejlépe je vložit spuštění
programu po startu do složky Po spuštění v nabídce Start nebo přímo v registru do položky
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\Run. Zda se spouští normálně nebo v SysTray
oblasti záleží už na samotném programu. |
|
2/2000 |
3 |
Parametry programu |
Nedokážu najít způsob, jak přečíst v programu ve Visual Basicu
parametry příkazové řádky. |
Parametry příkazové řádky vrací ve VB funkce Command. Návratová hodnota je typu String, tzn.
co uživatel zadal za názvem programu si už musíte "vypreparovat" sám. |
|
2/2000 |
3 |
Grafika |
Lze ve VB pracovat s grafikou ve více vrstvách? Vykreslím-li nějaký tvar pomocí Circle, PSet, Line a
chci část skrýt (vypnout hladinu), musím vše vymazat (cls) a poté znovu vykreslit viditelné.
Zkoušel jsem nastavit DrawMode = 7 a znovu vykreslit hladinu k vypnutí, ale nefunguje to (patrně kvůli AutoRedraw = True).
Jsou i jiné metody, popř. udělal jsem někde chybu? |
S hladinami VB pracovat neumí. Pokud chcete schovat nějakou kresbu, musíte ji znovu vykreslit.
Přitom je nutno mít nastaven režim XOR, tedy DrawMode = vbXorPen (nebo 7). To, že Vám to nefunguje, určitě
není nastavením AutoRedraw = True. Při režimu XOR je nutno si uvědomit, jak se vykresluje. Při kreslení
je provedena operace XOR s jednotlivými bity barvy pera a barvy pozadí na stejných pozicích. Výsledná barva je použita pro vykreslení
(např. "barva pera" XOR "barva pozadí" = "barva vykresleni" - 1111 XOR 0011 = 1100). A navíc, bavíme-li
se o barvě pozadí, nejde o pozadí formuláře, ale o barvu na formuláři v místě, kde budete vykreslovat.
Například:
Form1.DrawMode = vbXorPen
Form1.BackColor = RGB(0, 0, 0) 'Barva pozadi - cerna
Form1.ForeColor = RGB(255, 0, 0) 'Barva pera - cervena
Form1.Circle (500, 500), 200 'Nakresli kruznici
Form1.Circle (500, 500), 200 'Zrus kruznici
Pro první kružnici je výsledek brán z RGB(0,0,0) XOR RGB(255,0,0) = RGB(255,0,0). Při druhém
vykreslení je však již barva pozadí v místě kružnice červená, tj. RGB(255,0,0) a výsledkem
RGB(255,0,0) XOR RGB(255,0,0) je RGB(0,0,0), tedy barva pozadí formuláře, tzn. kružnice zmizí. |
|
2/2000 |
3 |
Tisk |
Jde ve Visual Basicu nějak tisknout na obálky? A jestli ano, tak jak? |
Visual Basic nemá žádnou přímou podporu tisku na obálky. Lze na ně samozřejmně tisknout
standardním způsobem, tj. nastavením formátu tiskárny na tu obálku, kterou potřebujete
a použítím metody Print objektu Printer. |
|
3/2000 |
3 |
ListBox |
Prosil by som Vás, keby ste mi poskytli odpoveď na môj problém.
Programujem vo Visual Basicu 4.0. Potreboval by som vedieť, ako sa dajú odstraňovať
položky z ListBoxu pri rozšírenom výbere (Multiselect = 2). |
ListBox bohužel nemá žádnou metodu pro odstranění všech označených položek. Proto musíte
projít všechny položky, zjistit, jestli jsou vybrány a pokud ano, odstranit je. Nějak takto:
Dim i As Long
i = 0
Do While i <= List1.ListCount - 1
If List1.Selected(i) Then
List1.RemoveItem i
Else
i = i + 1
End If
Loop
|
|
3/2000 |
3 |
Instalace |
Programuji ve Visual Basicu 6.0. Když vytvořím program, na mém počítači funguje bez
problémů. Jak ho ale spustím na jiném počítači, hlásí že chybí soubor MSVBVM60.DLL. Je možné
tento soubor nějak přilinkovat k samotnému programu? |
Ve Visual Basicu bohužel nic takového není možné. Pokud vytvoříte EXE soubor, nestačí jej
pouze zkopírovat na jiný počítač. Pro běh je potřeba již výše zmíněný soubor a většinou i
několik dalších, které nejdou přilinkovat k EXE. Proto bych vám doporučoval použít program
Package & Deployment Wizard, který vytvoří instalační program pro Váš program. |
|
3/2000 |
3 |
Systémové barvy |
Potřebuji zjistit systémové barvy, jako např. barva tlačítka, lišty programu apod.
Používám API funkci GetSysColor, ale nikdy nedostanu žádné číslo barvy. |
Tento problém může mít více příčin. Nejpravděpodobnější však bude špatné zadání parametru
funkce. Nelze totiž použít konstanty z VB, musíte použít konstanty definované v API prohlížeči
dodávaném s VB. Malý příklad:
Public Declare Function GetSysColor Lib "user32" Alias "GetSysColor" (ByVal nIndex As Long) As Long
Public Const COLOR_BTNFACE = 15
Public Const COLOR_BTNTEXT = 18
barva = GetSysColor(COLOR_BTNFACE)
|
|
3/2000 |
3 |
Síť |
Jak lze zjistit ve Visual Basicu adresu síťové karty počítače, na kterém právě běží
aplikace? |
Zjistit hardwarovou adresu síťové karty není až tak jednoduché, aby se vlezlo na tuto
stránku, proto zkuste tento
příklad. API funkcí, která vrací takovou
informaci je NetBios. |
Zkuste/VBasic/CCD/Otazky/nicadres.ccd |
4/2000 |
3 |
Detekce programů |
Potřeboval bych pomoci s programem, který má detekovat, jestli je spuštěno
více oken Internet Exploreru a v případě, že jsou spuštěny 3, aby se jedno
ukončilo. A také aby program fungoval hlavně pod Windows NT i 2000 a neměl by jít
ukončit. |
Jestli je spuštěn nějaký program, můžete zjistit pomocí API funkce GetWindow. Funkce
prochází všechna "okna" ve Windows (přesněji ta, která si řeknete, ale vy potřebujete projít
všechna) a dává jejich handle (pokud vám nevyhovuje GetWindow, zkuste EnumWindows).
Z toho můžete zase pomocí GetWindowText zjistit,
jestli je to Internet Explorer a dál už záleží na Vás. Níže uvedený příklad projde všechna
"okna" a vypíše jejich název. Jak udělat, aby program nešel ukončit pod NT nevím.
Ale podle toho co vím, tak půjde ukončit vždy, vždyť NT jsou serverový OS a ten by se
podle mého názoru neměl ptát programu, jestli chce ukončit nebo ne. Ale je to pouze domněnka,
nemám s NT moc zkušeností.
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Const GW_HWNDNEXT = 2
Private Const GW_CHILD = 5
Private Sub VypisOkna()
Dim desktop As Long, hwnd As Long
Dim title As String, delka As Long
hwnd = GetWindow(GetDesktopWindow, GW_CHILD)
Do While hwnd <> 0
hwnd = GetWindow(hwnd, GW_HWNDNEXT)
title = String(255, vbNullChar)
delka = GetWindowText(hwnd, title, 255)
title = Left(title, delka)
If delka > 0 Then Debug.Print title
Loop
End Sub
|
|
4/2000 |
3 |
Disky |
Zajímalo by mně, jak se dá ve Visual Basicu zjisit seriové číslo disku, na kterém se nachází můj
program. |
Seriové číslo disku lze zjistit pouze pomocí API, VB žádnou funkci nemá. API funkce,
která vám řekne seriové číslo je GetVolumeInformation.
Private Declare Function GetVolumeInformation Lib "kernel32" Alias "GetVolumeInformationA" (ByVal lpRootPathName As String, ByVal lpVolumeNameBuffer As String, ByVal nVolumeNameSize As Long, lpVolumeSerialNumber As Long, lpMaximumComponentLength As Long, lpFileSystemFlags As Long, ByVal lpFileSystemNameBuffer As String, ByVal nFileSystemNameSize As Long) As Long
Private Sub ZobrazSN(ByVal disk As String) 'disk - napr. C:\
Dim sn As Long, nazev As String, i1 As Long, i2 As Long, i3 As String, hw As Long, lw As Long
nazev = Space(14): i3 = Space(32)
GetVolumeInformation "C:\", nazev, Len(nazev), sn, i1, i2, i3, Len(i3)
hw = HiWord(sn) And &HFFFF&
lw = LoWord(sn) And &HFFFF&
MsgBox "Seriové číslo disku: " & Format(Hex(hw), "0000") & "-" & Format(Hex(lw), "0000")
End Sub
Private Function HiWord(ByVal dw As Long) As Integer
If dw And &H80000000 Then
HiWord = (dw \ 65535) - 1
Else
HiWord = dw \ 65535
End If
End Function
Private Function LoWord(ByVal dw As Long) As Integer
If dw And &H8000& Then
LoWord = &H8000 Or (dw And &H7FFF&)
Else
LoWord = dw And &HFFFF&
End If
End Function
|
|
4/2000 |
3 |
Hudba |
Jakým způsobem lze ve Visual Basicu přehrávat MID soubory. Nechci použít přehrávač integrovaný
ve Windows. |
Pokud chcete soubory přehrávat jednoduše, použijte prvek z VB, Microsoft Multimedia Control. Umí
přehrávat nejen MID, ale i WAV a audio CD. Chcete-li si z hudbou "hrát" více, musíte použít
API funkce MCI. Jejich popis by přesahoval možnosti této rubriky, pokud se o tom chcete něco
dozvědět, zkuste pro začátek stránku
Microsoftu. |
|
4/2000 |
3 |
DirectX |
Na ChipCD 3.2000 je příklad na přehrávání zvuku přes DirectX a tak se chci zeptat, jestli
na nějakém minulém CD nebylo něco o DirectDraw a případně jestli o tom bude něco v příštích
číslech. |
DirectX se bohužel nevěnujeme, příklady o DirectX jsou výhradně z Internetu nebo pokud
je zašle nějaký čtenář. Proto nemůžeme přesně říci, zda ještě nějaké budou. Pár příkladů na
použití DirectDraw bylo na Chip CD 7/1999. Na Internetu můžete nalézt informace a zdrojové
kódy týkající se DirectX např. na adresách www.chez.com/scribe a
msdn.microsoft.com/directx. Spousta odkazů
na další servery je na www.vb-web-directory.com/game/gam_dx.shtml |
|
5/2000 |
3 |
Formulář |
Mohli byste mi prosím vysvětlit, jak se vytvářejí formuláře, tzv. splash screen, tedy formuláře,
které se objeví na obrazovce, dokud se samotný program teprve inicializuje. |
Vytvářějí se úplně normálně, jako ostatní formuláře. Většinou však nemají titulkový pruh. To
způsobí nastavení vlastností BorderStyle = 3, Caption = "", ClipControls = False,
ControlBox = False. Zobrazení samotného formuláře potom bývá mezi prvními instrukcemi
programu a po provedení všech inicializací programu se formulář zase schová. Např.:
Private Sub Main()
frmSplash.Show
DoEvents
If App.Previnstance ... 'nějaké kontroly před spuštěním, otevření DB apod.
If GetSettings( ...
otevriDatabazi(cesta) ...
...
Load frmMain
Unload frmSplash
frmMain.Show 'hlavní formulář aplikace
End Sub
|
|
5/2000 |
3 |
Menu |
Pomocí API funkce InsertMenu si mohu do menu okna přidat co chci (např. "vždy
na vrchu"), ale vůbec nevím, jak zajistit, aby se při kliknutí na toto menu něco
provedlo. |
Při přidávání menu získáte jeho ID (čtvrtý parametr funkce InsertMenu). Pomocí
funkce SetWindowsLong nastavíte vlastní funkci pro obsluhu zpráv (řečeno zjednodušeně)
a v ní rozpoznáte (pomocí zmíněného ID), zda někdo zvolil přidanou položku v menu, kontrolou parametrů message
a wparam. Např.:
'====================== kód formuláře ======================
Private Sub Form_Load()
insertmymenu
End Sub
Private Sub Form_Unload(cancel As Boolean)
unloadmymenu
End Sub
'====================== kód modulu =========================
Private lngID As Long
Private lngOldProcessID As Long
Public Sub insertmymenu()
Dim hWndSystemMenu As Long
hWndSystemMenu = GetSystemMenu(frmMenuSample.hwnd, 0&) 'získej ID systémového menu
InsertMenu hWndSystemMenu, 0, MF_STRING, mlngID, "moje menu" 'vlož položku menu
'nastav novou funkci pro obsluhu zpráv
lngOldProcessID = SetWindowLong(Form1.hwnd, GWL_WNDPROC, AddressOf SystemMenuCallBack)
End Sub
Public Sub unloadmymenu()
'Nastav původní obsluhu zpráv
SetWindowLong Form1.hwnd, GWL_WNDPROC, lngOldProcessID
End Sub
Public Function SystemMenuCallBack(ByVal lnghwnd As Long, ByVal lngMessage _
As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If lngMessage = WM_SYSCOMMAND Then 'bylo kliknuto na syst. menu
Select Case wParam 'která položka to byla
Case lngID
msgbox "Moje menu"
Exit Function
Case Else
End Select
End If
SystemMenuCallBack =CallWindowProc(lngOldProcessID, lnghwnd, lngMessage, wParam, lParam)
End Function
|
|
5/2000 |
3 |
Modem |
Chtěl bych naprogramovat aplikaci, která by pomocí modemu zpřístupnila na jiném počítači
aplikaci s databází. Problém je v tom, že nevím, jak udělat, aby ta druhá aplikace
zdvihla telefon a začala komunikovat. Je vůbec možné něco takového vytvořit pomocí Visual Basicu? |
Takováto akce ve Visual Basicu udělat jde. Pomocí komponenty MSComm můžete vysílat
i přijímat data ze seriového portu, tzn. i AT příkazy pro modem, který je na tomto
portu připojen a těmi si můžete modem ovládat, jak chcete. |
|
5/2000 |
3 |
CommonDialog |
Mám dva problémy ve VB5. Nejde mi vyrobit ChooseFont dialog s použitím pouze API funkcí. Při
volání mi GetLastError vrátí chybu CDERR_STRUCTSIZE. Chtěl bych používat systémová okna pro
FindText a ReplaceText (opět API). Okna se mi zobrazí, ale pokud zvolím cokoliv jiného než
Storno, VB se zhroutí. |
Pravděpodobně je problém buď v definici struktury nebo není nastaveno, které fonty se mají
zobrazit, pro tiskárnu, obrazovku nebo obojí. Zkuste strukturu naplnit takto:
cf.lStructSize = Len(cf)
cf.hwndOwner = Form1.hWnd
cf.hDC = Printer.hDC
cf.Flags = CF_BOTH Or CF_EFFECTS Or CF_FORCEFONTEXIST Or CF_INITTOLOGFONTSTRUCT Or CF_LIMITSIZE
cf.nFontType = REGULAR_FONTTYPE
cf.nSizeMin = 10
cf.nSizeMax = 72
Pokud jde o druhý problém s dialogy pro vyhledávání a nahrazení textu, netuším proč to dělá
(kdo víte jak na to, napište).
|
|
5/2000 |
3 |
API |
Potřeboval bych pomocí API funkce SendMessage odkrýt hvězdičky u hesel. Handle TextBoxu už mám, jen nevím, co mám
doplnit do ostatních parametrů funkce SendMessage. |
Parametry funkce SendMessage dosaďte takto: hwnd = handle TextBoxu, message = EM_SETPASSWORDCHAR (&HCC),
wparam = 0, lparam = 0. Wparam nastavuje znak, který se zobrazí. Pokud je 0, jsou znaky vidět normálně. |
|
6/2000 |
3 |
Handle aplikace |
Poradili byste mi jak mám získat handle aplikace, když znám její název? |
Použijte API funkci FindWindow. Má dva parametry. První je třída (pokud neznáte, nastavte 0),
druhý je název, tj. text v titulkovém pruhu. |
|
6/2000 |
3 |
Soubory |
Potřebuji zapsat nějaká data do souboru, ale tak, abych ten souboru
měl jako čistý ASCII text, a ne soubor, ve kterém mám na začátku
značku s neidentifikovatelným znakem. Příkaz Put vyžaduje číslo
pozice, a tuto pozici pak nejspíš mám ve formě toho znaku. Otázka: Jde zapsat něco
do soboru tak, abych tam měl jenom ten text co potřebuji a nic jiného? |
Pro takový zápis je nejvhodnější otevřít soubor jako textový (u MS tomu říkají
sekvenční přístup - mód Input, Output nebo Append). Potom použijte funkci
Print # . Zapisuje data tak jak jsou do souboru (za každým zápisem udělá nový řádek).
Ale funkce PUT udělá podobnou službu (v souboru otevřeném v binárním módu), bez toho aby něco přidávala. Např.:
Dim i As Long, retezec As String
i = FreeFile
Open "C:\pokus1.txt" For Binary As #i
retezec = "prvni" & Chr(13) & Chr(10) & "druhy" & Chr(13) & Chr(10) & "treti"
Put #i, , retezec
Close i
i = FreeFile
Open "C:\pokus2.txt" For Output As #i
Print #i, "prvni"
Print #i, "druhy"
Print #i, "treti"
Close i
Oba dva tyto kódy vytvoří stejný soubor (pouze u druhého bude za posledním
znakem ještě znak nového řádku). Pokud pracujete s textovými soubory, doporučoval
bych zkusit rozšíření Microsoft Scripting Runtime a jeho objekty FileSystemObject ,
TextStream a File . Na takovou práci jsou to velmi vhodné objekty.
|
|
6/2000 |
3 |
Formulář |
Potřeboval bych vědět jak mám udělat program, který budu mít v pozadí,
ale bude jako aktivní pro ostatní programy |
Pokud myslíte program, který bude spuštěný, ale nebude vidět, stačí
jej udělat minimalizovaný. Anebo pokud nemá být vidět v liště Start,
tak nastavte zobrazenému formuláři vlastnost ShowInTaskbar na False . |
|
6/2000 |
3 |
Adresáře |
Jakou funkcí lze vyvolat dialogové okno "Výběr adresáře"? |
Takové okno se vyvolá API funkcí SHBrowseForFolder .
Abyste zjistil, kterou složku uživatel zvolil, musíte použít ještě další funkce:
Dim bi As BROWSEINFO, pidl As Long, path As String
bi.hOwner = Me.hwnd
bi.lpszTitle = "Vyberte adresář pro zálohu a stiskněte tlačítko OK."
bi.ulFlags = BIF_RETURNONLYFSDIRS
pidl = SHBrowseForFolder(bi) 'dialog
path = Space(512)
SHGetPathFromIDList ByVal pidl, ByVal path
Deklarace funkcí a typů pak vypadá takto:
Public Declare Function SHGetPathFromIDList Lib "shell32.dll" Alias
"SHGetPathFromIDListA" (ByVal pidl As Long, ByVal pszPath As String) As Long
Public Declare Function SHBrowseForFolder Lib "shell32.dll" Alias
"SHBrowseForFolderA" (lpBrowseInfo As BROWSEINFO) As Long
Public Type BROWSEINFO
hOwner As Long
pidlRoot As Long
pszDisplayName As String
lpszTitle As String
ulFlags As Long
lpfn As Long
lParam As Long
iImage As Long
End Type
Public Const BIF_RETURNONLYFSDIRS = &H1
Public Const BIF_DONTGOBELOWDOMAIN = &H2
Public Const BIF_STATUSTEXT = &H4
Public Const BIF_RETURNFSANCESTORS = &H8
Public Const BIF_BROWSEFORCOMPUTER = &H1000
Public Const BIF_BROWSEFORPRINTER = &H2000
|
|
6/2000 |
3 |
Kontrola spuštění programů |
Potřebuji udělat program, který se sám vypne, jakmile se spustí Internet Explorer nebo nějaká
jiná aplikace. |
Zkuste tento příklad. Pomocí Timeru každou sekundu
zkontroluje spuštěné programy a pokud mezi nimi nalezne Internet Explorer, ukončí se. |
Zkuste/VBasic/CCD/Otazky/endprg.ccd |
6/2000 |
3 |
Síť |
Rád bych věděl, jak se dá ve Visual Basicu zjistit, který uživatel je v systému
Windows (prihlašovací okno po startu) přihlášen. Zkoušel jsem různe API funkce,
ale zatím se mi to nepodařilo. |
Použijte API funkci GetUserName .
Declare Function GetUserName Lib "advapi32.dll" Alias "GetUserNameA" (ByVal
lpBuffer As String, nSize As Long) As Long
Dim jm As String, ret As Long
jm=Space(255)
ret=GetUserName(jm, 255)
MsgBox "Jméno uživatele: " & jm
|
|
6/2000 |
3 |
CommonDialog |
Ve svém programu jsem se snažil pomocí funkce GetOpenFileName a
struktury OpenFileName otevřít libovolný soubor.
Okno "Otevřít soubor" se mi zobrazí, ale já nevím, jak mám z něho dostat jméno
souboru a cestu k souboru, který jsem si vybral. |
Jméno souboru s cestou je vráceno v proměnné typu OPENFILENAME v lpstrFile . Ale
než spustíte funkci GetOpenFileName , musíte ji inicializovat, třeba nějak
takto:
Dim filebox As OPENFILENAME
filebox.lStructSize = Len(filebox) 'velikost struktury
filebox.hwndOwner = Form1.hWnd 'handle volajiciho formulare
filebox.lpstrTitle = "Open File" 'titulek
filebox.lpstrFilter = "textové soubory" & vbNullChar & "*.txt" & vbNullChar
& "Všechny soubory" & vbNullChar & "*.*" & vbNullChar & vbNullChar 'filtr
filebox.lpstrFile = Space(255) 'tady naplnime promennou pro vraceni jmena a
cesty k souboru
filebox.nMaxFile = 255 'max. delka souboru plus cesta
filebox.lpstrFileTitle = Space(255) ' promenna pro nazev souboru
filebox.nMaxFileTitle = 255 'max. delka nazvu souboru
filebox.flags = OFN_PATHMUSTEXIST Or OFN_FILEMUSTEXIST Or OFN_HIDEREADONLY
'dalsi nastaveni
|
|
6/2000 |
3 |
Grafika |
Jak se dá ve VB 5 udělat, aby se nějaký objekt (např Image)
pohyboval po elipse nebo i po jiné křivce - čtverec, kruh, obdélník... a jak se dá
udělat, aby se v jednom bodě elipsy pohyboval pomaleji než na jiném bodě (protější
strana) a mezi těmito body rovnoměrně zrychloval? |
Většina prvků může za běhu programu měnit svoji polohu. Jakým směrem,
to už záleží jenom na vás. Pokud chcete pohyb po kružnici, elipse nebo jakýkoli
jiný tvar, musíte si sám vypočítávat následujíci body pro pohyb
(kružnici či elipsu třeba pomocí Bressenhamova algoritmu).
Zrychlování a zpomalování zaleží na tom, jestli budete objektem pohybovat přes jeden,
dva či třeba tři body nebo zvolíte po každém pohybu nějaké zpoždění.
Pokud někoho ze čtenářů napadne lepší řešení, napiště nám jej, rádi jej zveřejníme. |
|
6/2000 |
3 |
Kontrola spuštění programů |
Mohli byste mi prosím poradit, jak vytvořit program, který když se spustí nějaký jiný program, např. Internet
Explorer, ukončí sám sebe? |
Takový program je možno vytvořit pomocí prvku Timer . Jednoduše budete kontrolovat (třeba každých 30
sekund) spuštěné programy a bude-li mezi nimi ten, který hledáte, ukončíte svůj program. Příklad
zde. |
Zkuste/VBasic/CCD/Otazky/ctrlprg.ccd |
7/2000 |
3 |
Ukončení programu |
Chtěl bych z kódu Visual Basicu vypnout třeba Explorer. Po delším bádání se mi to podařilo zaktivováním
okna Exploreru a simulací stisku ALT + F4. Tento způsob je ale velice zdlouhavý a nepřehledný. Existuje
i nějaký jiný způsob, třeba pomocí API? Také by mě zajímalo, kde lze sehnat nějaký přehled API funkcí. |
Vypnout jinou aplikaci můžete pomocí API funkce SendMessage a zprávou WM_CLOSE . Některé
programy však tímto způsobem vypnout nejdou, např. Internet Explorer. Proto žádáme čtenáře, víte-li jak na Internet
Explorer, napište nám.
Přehled API funkcí bude trochu problém. Buď jde o knihy, které přímo učí programovat ve Windows (např. Programovaní
ve Windows 95), ale v těch nenajdete seznam API. Dále vyšla třeba kniha WIN32 API (2. díly), kde je size seznam
API funkcí, ale tradičně v jazyce C. Nějaká podobná kniha pro programátory ve Visual Basicu u nás zatím není. |
|
7/2000 |
3 |
Více procesorů |
Existuje nějaký popis (a vůbec možnost) jak psát kód ve Visual Basicu 6 Ent. pro víceprocesorové
stroje? Mám na mysli efektivní kód využívající více resp. dvou procesorů. |
Ve verzi 6.0 žádná podpora pro tvorbu takových aplikací není, vše byste musel dělat pomocí API.
Na stránce http://msdn.microsoft.com/library/psdk/winbase/prothred_0n03.htm
si můžete něco o této problematice přečíst. Na http://msdn.microsoft.com/library/psdk/winbase/prothred_4zg3.htm
najdete ještě další informace. Vše by se mělo údajně zlepšit s příchodem VB 7.0, který už bude mít vytvořené vlastní objekty
a funkce pro tvorbu multi-threaded aplikací. |
|
7/2000 |
3 |
Internet Explorer |
Jak by se dalo v mém programu donutit Internet Explorer k tomu, aby mi zobrazil určitou stránku na Internetu? Spustit
ho pomocí API ShellExecute nebude problém, ale už nevím, jak zobrazit zadanou stránku. Jde to vůbec? |
Použijte spíše objekt InternetExplorer. Pomocí metody Navigate mu můžete
určit stránku k zobrazení. Pokud chcete nutně použít API, použijte
ShellExecute , ale zadejte tyto parametry: hWnd, "open", "www.stranka.ww" ... Horší je to v případě, že je
s HTML asociován jiný prohlížeč než IE. |
|
7/2000 |
3 |
Klávesnice |
Potřebuji v programu simulovat stisk klávesy ESC. Zkoušel jsem funkci GetKeyboardState , ale po zadání parametru
27 (ESC) mi program spadne. |
Funkce GetKeyboardState slouží k zjištění stavu klávesnice. Pokud byste
chtěl něco nastavovat, je tu funkce SetKeyboardState (nebo pro kombinaci
myši, klávesnice a dalších vstupů funkce SetInput ). Ale pro Vaše účely je
mnohem lepší API keybd_event . Asi nějak takto:
Declare Sub keybd_event Lib "user32.dll" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)
Const VK_ESCAPE = &H1B
Const KEYEVENTF_KEYUP = &H2
keybd_event VK_ESCAPE, 0, 0, 0 'dolu
keybd_event VK_ESCAPE, 0, KEYEVENTF_KEYUP, 0 'nahoru
|
|
7/2000 |
3 |
Disky |
Potřebuji nějak ve Visual Basicu zjistit, zda je v CD-Rom mechanice vloženo CD. |
Zda je v mechanice CD lze zjistit třeba tak, že se pokusíte z něj něco přečíst. Pomocí API funkcí GetLogicalDriveStrings
a GetDriveType zjistíte písmeno mechaniky a pak zkusíte kopírovat nebo zjistit volné místo. Když CD v mechanice
nebude, nastane chyba. |
|
7/2000 |
3 |
Informace na Internetu |
Můžete napsat pár internetových adres o Visual Basicu? Nejlépe nějakou diskusní skupinu. |
Na serveru csnews.vslib.cz je skupina cz.comp.lang.basic.visual nebo
pokud chcete přes WWW prohlížeč, tak třeba na http://forums.oreilly.com/~vb/. Na
http://www.cetus-links.org/oo_visual_basic.html najdete více než slušný přehled různých diskuzních skupin o VB. |
|
7/2000 |
3 |
Timer |
Potřebuji poradit ohledně ovládacího prvku Timer. Jeho interval je
pouze na minutu a já bych potřeboval asi tak 10 až 15 minut. Nevíte o
nějakem jiném ovládacím prvku? Jestli ne, pak by mi stačil příkaz pro
pozastavení běhu programu na určitou dobu. |
K pozastavení běhu programu ve VB nic není, musíte použít API funkci Sleep .
Public Declare Sub Sleep Lib "kernel32" Alias "Sleep" (ByVal dwMilliseconds As Long)
Místo jiného ovládacího prvku bych použil spíše API funkce SetTimer a KillTimer . Jak
je použít najdete v této rubrice v čísle 6/2000.
|
|
7/2000 |
3 |
Systém |
Chtěl bych se zeptat, jak mohu vypnout Windows do klasického "Nyní můžete
počítač bez obav vypnout" (bez žádného dalšího odkliknutí) pomocí obyčejného tlačítka (Např.: "CB1") na mém formuláři
a také jak bych mohl ukončit nějaký běžící program Např.: MS Word pomocí druhého tlačítka "CB2" |
Vypnout Windows je možné pomocí API funkce ExitWindowsEx :
Declare Function ExitWindowsEx Lib "user32.dll" (ByVal uFlags As Long, ByVal
dwReserved As Long) As Long
První parametr nastavte na EWX_POWEROFF = 8 a pokud potřebujete přidejte i EWX_FORCE = 4
(nebude se ptát aplikací jestli je může vypnout nebo ne). Takže asi takto:
ExitWindowsEx EWX_POWEROFF + EWX_FORCE, 0
Ukončit běžící program můžete pomocí API funkce SendMessage se zprávou WM_CLOSE (WM_CLOSE = &H10).
|
|
7/2000 |
3 |
Aktivní prvek |
Jak mám zjistit, který prvek má právě focus? Vím že existuje funkce SetFocus , která jej nastaví, ale já potřebuji
vědět, který prvek jej má. |
Každý formulář má vlastnost ActiveControl , která ukazuje na aktuální prvek, tj. ten, který má focus. Tzn. přes
tuto vlastnost můžete s prvkem jednoduše pracovat. Např.:
MsgBox Form1.ActiveControl.Name
Form1.ActiveControl.Caption="tlacitko 1"
|
|
8/2000 |
3 |
Databáze |
V Accessovské databázi mám dvě tabulky. Jedna (Autor) souží jako číselník
autorů a druhá (Knihovna) slouží k evidenci knih. Vytvořím-li si ve VB
formulář na ukládání dat do tabulky KNIHOVNA, jak docílím toho, aby se data o
autorech pomocí ComboBoxu načítala z tabulky AUTOR? A dále jak docílit
toho, zadám-li např. do položky Jazyk údaj "český", aby se v ComboBoxu
objevili jenom ti autoři, co mají v číselníku autorů uvedeno v položce Jazyk údaj "český"? |
Je důležité, jestli chcete pro přístup k databázi použít Data prvek a na něj
vázané prvky. Pokud ano, použijte DBCombo. Má vlastnosti RowSource a ListField, pomocí
nichž se navážete na jiný Data prvek, který bude obsahovat informace z tabulky Autori.
Tyto informace se potom zobrazí v seznamu ComboBoxu. Na změnu jazyka se potom může
měnit zdroj Data prvku, na to stačí jednoduchý SQL dotaz.
Pokud nechcete použít vázané prvky a Data prvek, tak stačí vytvořit Recordset
s informacemi o autorech a jeho obsah "natáhnout" do seznamu ComboBoxu. |
|
8/2000 |
3 |
VBA |
Když chci spustit makro v jazyce VBA, dostanu tuto hlášku:
The macros in this project are disabled. Please refer to the online help or documentation of the host application to determine how to enable macros. |
Nejsme bohužel žádní přeborníci ve VBA, ale podle tazatele námi navržený postup funguje, takže asi takto:
Problém je způsoben zákazem provádění maker. Je třeba zapnout antivirovou ochranu
(ve Wordu to je menu Nástroje -> Možnosti, záložka Obecné, položka Antivirová ochrana maker) a spustit
aplikaci znovu (Word). Když po dotazu dáte povolit makra, mělo by to fungovat. |
|
8/2000 |
3 |
Tvorba ActiveX |
Používám VB 5.0 enterprise edition. Ten umožňuje vytváření vlastních OCX objektů. Potíž je v tom, že když
vytvořím projekt ocx, přidám do něho formulář a modul (pro sdílení polí proměnných), tyto pole se nemění, tzn. že když
si na testovací formulář položím několik těchto objektů, v jednom z nich něco změním, okamžitě se to promítne
i do ostatních - nepracují nezávisle na sobě, jako by sdílely proměnné. |
Takové chování je v pořádku. Pokud něco v modulu nadefinujete jako
Public , je to sdílené pro všechny instance prvku.
To je právě ten rozdíl mezi třídou a modulem, třída je pouze vzor,
podle kterého se vytváří instance, kdežto modul je vlastně už "instance". |
|
8/2000 |
3 |
Kontrola spuštění programů |
Když bude aktivní aplikace (že nebude na pozadí), která bude mít v titulku např.
"Internet Explorer", aby se provedla určitá funkce a obráceně, když
nebude aplikace s tímto titulkem aktivní (bude na pozadí), aby byla vyvolána zase jiná funkce. |
Můžete použít Timer, který bude v nějakém časovém intervalu kontrolovat, která aplikace je aktivní pomocí API
GetForegroundWindow (vrací handle aktivní aplikace). Pomocí GetWindowText potom zjistíte
titulek této aplikace. No a potom už provádíte ty svoje funkce. |
|
8/2000 |
3 |
Speciální složky |
Můžete prosím poradit, jak programově zjistím cestu ke složce oblíbené položky? |
Nějak takto:
ret = SHGetSpecialFolderLocation(0, &H6, idl)
If ret = 0 Then
cesta = Space(255)
SHGetPathFromIDList idl.mkid.cb, cesta
MsgBox cesta 'toto je cesta ke složce oblíbené položky
End If
Deklarace funkcí a typů:
Private Type SHITEMID
cb As Long
abID As Byte
End Type
Private Type ITEMIDLIST
mkid As SHITEMID
End Type
Private Declare Function SHGetPathFromIDList Lib "shell32.dll" Alias "SHGetPathFromIDListA" (ByVal pidl As Long, ByVal pszPath As String) As Long
Private Declare Function SHGetSpecialFolderLocation Lib "shell32.dll" (ByVal hwndOwner As Long, ByVal nFolder As Long, pidl As ITEMIDLIST) As Long
|
|
8/2000 |
3 |
Formulář |
Chtěl jsem si udělat program, který bude mít více než jedno okno.
Ty vedlejší by se měly přilepovat k oknu hlavnímu (tak jako třeba
PlayList u WinAMPu), ale nevěděl jsem si s tím rady. Neustále se
mi stávalo (když se mi konečně povedlo něco napsat), že když se
okno přilepilo, a já jej odtahoval, tak pořád nepříjemně problikávalo.
Mohli by jste mi napsat nějaký jednoduchý příklad na přilepování? |
Trochu složitější příklad, proto jsme vytvořili projekt ve VB, který si můžete zkopírovat.
Funguje to tak, že pokud je ve Windows nastaveno zobrazovaní obsahu okna během přetahování, přetahuji se obě naráz,
pokud to není nastaveno, je vidět pouze obrys toho jednoho a až po přetažení se obě objeví zase u sebe. |
Zkuste/VBasic/CCD/Otazky/winmove.ccd |
8/2000 |
3 |
PictureBox |
Potřeboval bych v PictureBoxu (popřípadě ve Frame) vypsat text na určité souřadnice, ale ne přes Label.
Vím že C++ Builder má takovou funkci: Image->Canvas->TextOutA(x,y,text).
Jde to nějak udělat i ve VB? |
PictureBox má metodu Print . Nenabízí ji sice v seznamu ani není vidět v
Object browseru, ale je tam. No a pomocí vlastností CurrentX a CurrentY
nastavíte, kam se má text vypsat:
Pic1.CurrentX = 500
Pic1.CurrentY = 150
Pic1.Print "Text na x 500 a y 150"
|
|
8/2000 |
3 |
Myš |
Ve formuláři mám rámec a v něm několik textových polí, do kterých se zadávají údaje.
Potřebuji omezit pohyblivost myši pouze na tento rámec, dokud uživatel nestlačí tlačítko "Ulož". |
Výřez, ve kterém se má myš pohybovat, lze nastavit pomocí API funkce ClipCursor .
Private Type RECT
left As Long
top As Long
right As Long
bottom As Long
End Type
Private Declare Function ClipCursor Lib "user32" (lpRect As Any) As Long
Dim r As RECT
r.left = 100
r.right = 200
r.bottom = 200
r.top = 100
ClipCursor r
Pokud to chcete nastavit zpět na celou obrazovku, stačí nastavit zpět na
puvodní hodnoty. Nejlépe to lze takto (GetDesktopWindow a GetWindowRect jsou
také API funkce, jejich deklaraci naleznete v API Vieweru):
Dim r As RECT, retval As Long, deskhWnd As Long
deskhWnd = GetDesktopWindow()
GetWindowRect deskhWnd, r
ClipCursor r
|
|
8/2000 |
3 |
ListView |
Zajímalo by mně, jak se dá udělat prostředí správce souborů, známé např. ze
Servant Salamanderu. Standardní komponenty se na to nehodí, nebo
aspoň myslím, že ne. Jde mi o to, aby se dalo přesouvat
kurzorovými klávesami po souborech, a nevím, jak by se dalo přesouvat
o adresář výše pomocí "dvou teček". |
Můžete použít prvek ListView. Sloupců může mít dostatek na správce souborů, pohybovat se po jeho položkách
je pomocí myší a klávesami bez problémů. Pokud jde o dvě tečky, vždy můžete klidně jako první položku seznamu
zobrazit dvě tečky a při kliknutí na ně vyčistit seznam a načíst soubory z nadřazené složky. |
|
8/2000 |
3 |
Nápověda |
Poradili byste mi, zda lze ve VB5 vytvářet soubory typu Help? |
Přímo ve VB to možné není. Ale s VB se dodávají dva nástroje, pomocí kterých to možné je.
Záleží na tom, jaký help chcete vytvořit. Pokud klasický HLP, musíte si vytvořit text pomocí nějakého
editoru, který umí formát RTF, např. Word. Další věci jako rejstříky apod. se potom vytváří pomocí
Help Workshopu. Pomocí něj také zkompilujete výsledný HLP soubor, který se dá potom jednoduše
použít ve VB.
Pokud chcete HTML help, vytvoříte normální HTML soubory, které pomocí HTML Help Workshopu
zkompilujete do výsledného CHM souboru. Jeho použití je však ve VB zatím poněkud složitější, není
pro něj žádná podpora, vše se musí dělat pomocí API. A navíc tento formát nepodporují Windows 95. |
|
8/2000 |
3 |
Formulář |
Potřebuji přesměrovat události hlavního formuláře na svou
proceduru, čehož jsem také dosáhl API funkcí SetWindowLong .
Problém ale vznikl v tom, že někdy nastane situace, kdy se form
po stištění tlačítka close (vpravo nahoře...) schová, ale
aplikace se neukončí.
Přidal jsem tedy do Form_Unload příkaz End a VB krachne (Program
provedl neplatnou operaci....). Pokud ale z Form_Load a Form_Unload odstraním přesměrování
událostí okna, vše proběhne v pořádku. |
Tady bohužel není moc co radit. Ukončovat takhle program, v případě přesměrování
událostí, není ve VB nijak vyřešeno. Ono vůbec nejsou ve VB takové akce
doporučovány, ale na druhou stranu je to někdy potřeba. Já bych se
přimlouval to End zrušit (to vám stejně nic jiného nezbývá) a zkontrolovat
si pořádně zdrojový kód, protože to, že se aplikace nezastaví, je problém
někde v kódu, neuvolněný objekt, formulář apod. |
|
8/2000 |
3 |
Internet |
Mám problém, který se týká Internetu.
Když znám IP adresu druhého počítače, který je právě připojen, jak můžu na ní odeslat nějaká data (libovolná)?
Zároveň jak mohu odchytit data, která přišla (dejme tomu ze stejného programu) z toho druhého počítače?
Chtěl bych to využít k tomu, aby bylo možno jedním programem (který je na dvou počítačích) přijímat text
nebo libovolná data pomocí Internetu. |
Můžete použít prvky Microsoft Winsock Control nebo Microsoft Internet Transfer Control. Použití je u obou
velice jednoduché a je vysvětleno v MSDN. |
|
8/2000 |
3 |
Obecné informace |
Před čtyřmi měsíci jsem vám psal dotaz, ke kterému jsem dostal hned odpověď. Ale můj dotaz zatím nevyšel na žádném
Chipu. Proč to? |
Dotazů dostáváme v poslední době tolik, že by to vydalo na samostatnou konferenci.
Proto se sem snažíme dávat jen ty, které nás nějak zaujali a o kterých si myslíme, že poradí více čtenářům.
Také je spousta dotazů na věci, které už na Chipu vyšly, proto je zde znovu neopakujeme. Proto pošlete-li nám dotaz
na který dostanete odpověď, která se zde neobjeví do jednoho nebo dvou měsíců, už se pravděpodobně neobjeví vůbec.
Také se nás jeden čtenář ptal, proč jsme mu neodpověděli. Ono se totiž může stát, že váš e-mail skončí "bůhvíkde"
jestli vůbec někde a k nám nedojde. Proto pokud vám nepřijde třeba do týdne odpověď, pošlete jej znovu. |
|
9/2000 |
3 |
Obecné informace |
Chci se zeptat, proč byly některé moje dotazy přeloženy ze slovenštiny do češtiny. |
Protože se spousta čtenářů ptá ve spěchu, většinou by se takový dotaz nedal publikovat.
Proto znění dotazů většinou upravujeme, aby to alespoň trochu vypadalo, a také přidáváme
češtinu (většina dotazů totiž chodí v CESTINE, což je samozřejmě v pořádku, ale ne na tuto stránku). No a
protože naše znalost slovenštiny je nevalná, vypadal by takový upravený dotaz
opravdu hrozně. Proto je překládáme do češtiny. |
|
9/2000 |
3 |
Menu |
V programu mám menu, mnuDel, které má klávesovou zkratku Del, tj. když stisknu klávesu Del,
provede se kód v události Click tohoto menu. Na tomto formuláři i TextBox txtFind
a když v něm zmáčknu Del, neprovede se smazání textu, ale zase udlásto Click toho menu. Takže
jsem problém vyřešil takto:
Private Sub mnuDel_Click()
If frmStart.ActiveControl.Name = "txtFind" Then Exit Sub
.
.
End Sub
Tj. menu mnuDel se nevyvolá, ale neprovede se ani výmaz textu v TextBoxu. Nevíte jak
tohle obejít?
|
Tento problém není zatím nijak vyřešen (alespoň to tvrdí MS na své stránce). Jedna z možností,
jak to obejít, je nastavit KeyPreview toho formuláře na True
a potom v události KeyDown tohoto formuláře odchytávat klávesy. No a pokud
je stisknuto Del a aktivní prvek není txtFind, spusti událost Click toho menu.
If KeyCode = vbKeyDelete Then
If Me.ActiveControl.Name <> "txtFind" Then
mnuDel_Click
End If
End If
|
|
9/2000 |
3 |
Soubory |
Potřebuji na vybraném disku vyhledat všechny soubory nějakého typu, např bitmapy. Jak docílím
toho, aby program vyhledával automaticky i všechny adresáře a podadresáře? |
Nejlepší, z hlediska Visual Basicu, by bylo použití příkazu Dir . Protože
však chcete prohledávat celý disk, tj. i podadresáře, je ideální použít rekurzi. Příkaz
Dir si bohužel při návratu do funkce nepamatuje své původní nastavení. Proto
je rychlejší použít APi funkce FindFirstFile a FindNextFile .
V příkladu pro zkrácení neuvádíme deklarace funkcí, typů a konstant, všechny najdete
v API Vieweru.
'funkce vrací kolekci, která obsahuje názvy všech požadovaných souborů i s cestou
Public Sub FindFile(ByVal strFolder As String, ByVal strFile As String, colFiles As Collection)
Dim hSearch As Long, udtFindData As WIN32_FIND_DATA, strTmp As String
Dim i As Long, ret As Long
If Right(strFolder, 1) <> "\" Then strFolder = strFolder & "\"
hSearch = FindFirstFile(strFolder & "*.*", udtFindData)
If hSearch = INVALID_HNADLE_VALUE Then Exit Sub
ret = 1
Do While ret <> 0
i = InStr(1, udtFindData.cFileName, Chr(0))
strTmp = IIf((i = 0), udtFindData.cFileName, Left(udtFindData.cFileName, i - 1))
If udtFindData.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY Then
If strTmp <> "." And strTmp <> ".." Then
FindFile strFolder & strTmp, strFile, colFiles
End If
Else
If strTmp Like strFile Then
colFiles.Add strFolder & strTmp
End If
End If
ret = FindNextFile(hSearch, udtFindData)
Loop
FindClose hSearch
End Sub
'použití
Dim soubory As New Collection, i As Long
FindFile "D:\", "*.jpg", soubory
For i = 1 To soubory.Count
Debug.Print soubory(i)
Next i
|
|
9/2000 |
3 |
DBGrid |
Potřeboval bych poradit ohledně ovládacího prvku DataGrid.
Mám tabulku v Excelu a potřeboval bych program ve Visual Basicu propojit s Excelem,
tzn. načíst tuto tabulku do programu. Předpokládám, že se to bude dít pomocí DataGridu,
ale nevím, jak to mám udělat. |
Možností propojení s Excelem je spousta. Z vašeho dotazu ale předpokládám, že chcete
data z listu v Excelu zobrazit v DataGridu. Nejjednodušší je použít
prvek Data a DBGrid. V prvku Data nastavte vlastost Connect na vaši
verzi Excelu (je tam nabídka, není problém), DatabaseName na název
souboru z Excelu a RecordSource na vybraný list (opět je tam nabídka).
DataGridu potom již stačí nastavit DataSource na název prvku Data a je hotovo. |
|
9/2000 |
3 |
Řetězce |
Potřebuji zjistit, zda nějaký řetězec obsahuje jiný řetězec. |
Na to je nejlepší funkce InStr , která dělá přesně to co potřebujete. Nebo
můžete použít operátor Like , který dělá něco podobného. Přesné použití
najdete v MSDN. |
|
9/2000 |
3 |
Obecné informace |
Které soubory si mám nahrát na svůj počítač, abych nemusel při hledání informací nebo studiu Visual Basicu
neustále číst z CD. |
Pokud chcete celou rubriku VB, tak celý adresář VBasic z adresáře Zkuste. Chcete-li pouze seriál nebo jinou část,
vždy pouze odpovídající HTML soubor z adresáře Zkuste\VBasic (v případě seriálu je to serial.htm atp.)
a dva související podadresáře, např pro seriál je to Data\Serial a CCD\Serial, pro activex to je Data\ActiveX
a CCD\ActiveX atd. |
|
10/2000 |
3 |
ListBox |
Jak zjistím nejdelší položku v ListBoxu a na základě této délky nastavím horizontální posuvník? |
Horizontální posuvník nastavíte zasláním zprávy LB_SETHORIZONTALEXTENT příslušnému ListBoxu s délkou v pixelech.
SendMessage List1.hwnd, LB_SETHORIZONTALEXTENT, lText/Screen.TwipsPerPixelX, 0&
Hodnota lText je nejdelší položka v ListBoxu zjištěná takto:
Dim i As Long, lText As Long, tmp As Long
lText = 0
For i = 0 To List1.ListCount - 1
tmp = TextWidth(List1.List(i))
If tmp > lText Then lText = tmp
Next i
lText = lText + TextWidth(" ")
|
|
10/2000 |
3 |
Databáze |
Potřebuji v databázi najít nějaký záznam, ale nevím jak. Zkoušel jsem tento kód (níže uvedený), ale bohužel
nefunguje.
propmpt = "Zadej úplné jméno pro hledání"
searchStr = InputBox(prompt$, "hledaný řetězec")
Data1.Recordset.Index = "NázevFirmy"
Data1.Recordset.Seek "=", searchStr
|
Problém je v použití metody Seek . Funguje pouze pro sady záznamu (Recordsety) otevřené jako tabulka, tzn.
buď dbOpenTable nebo při použití prvku Data, což je váš případ, nastavit vlastnost RecordsetType
prvku Data na hodnotu 0 neboli Table . Pokud nechcete otevírat Recodset jako tabulku, musíte
použít tento kód:
propmpt = "Zadej úplné jméno pro hledání"
searchStr = InputBox(prompt$, "hledaný řetězec")
Data1.Recordset.FindFirst "NázevFirmy='" & searchStr & "'"
|
|
10/2000 |
3 |
Systém |
Nevíte jak udělat, aby při ukončení Windows můj program dal hlášení, že je v CD-Rom jednotce vloženo CD?. |
Při ukončování Windows standardním způsobem, tj. pomocí nabídky Start - Vypnout, je všem aplikacím zaslána
zpráva WM_QUERYENDSESSION . Tuto zprávu musíte odchytit a potom zjistit, zda je v mechanice vloženo
CD třeba zjištěním volného místa pomocí vlastnosti FreeSpace objektu Drive (rozšíření
Microsoft Scripting Runtime). Pokud není požadovaný disk přístupný (tj. CD v mechanice není), vyvolá chybu,
kterou lze samozřejmě ošetřit např. takto:
On Error Resume Next
Set fso = CreateObject("Scripting.FileSystemObject")
i = fso.Drives(strDrive).FreeSpace
If Err.Number = 0 Then
Debug.Print "CD je v mechanice"
End If
On Error GoTo 0
|
|
10/2000 |
3 |
Spuštění po startu |
Jak je možné nastavit program tak, aby se spouštěl hned po startu Windows? |
Programy, které se spouštějí hned po startu Windows se umísťují do složky Po spuštění (stačí umístit zástupce)
nebo do registru do větve HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run. Pomocí příkazů
VB však nelze do tohoto místa registru zapisovat, proto musíte použít API funkce (jejich deklaraci naleznete v
API Text Vieweru).
Dim ret As Long, h1 As String
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\Microsoft\Windows\CurrentVersion\Run", 0, KEY_ALL_ACCESS, hKey)
If ret = 0 Then
h1 = "c:\project1.exe"
RegSetValueEx hKey, "MujProgram", 0, REG_SZ, h1, Len(h1)
RegCloseKey hKey
End If
|
|
11/2000 |
3 |
Chybové zprávy |
Zajímalo by mě, jak je možné zjistit, kde, tj. v jakém modulu, proceduře nebo funkci, došlo k chybě. Chtěl bych
ukládat chybové hlášky do log souboru, ale objekt Err tuto informaci neposkytuje. |
Visual Basic bohužel nic takového neumožňuje. Jedině že byste si to ošetřil sám, ukládáním názvu funkce a čísla
řádku do globální proměnné a tu kontroloval. Nebo použít lokální ošetření chyb, což však zase není příliš přehledné. |
|
11/2000 |
3 |
Speciální složky |
Jde ve Visual Basicu napsat program pro vymazání složky TEMP? |
Pro práci se složkou můžete ve VB použít několik funkcí. Např. pomocí API getTempPath zjistíte
cestu a pomocí příkazu Kill vše z této cesty smažete. Pokud nechcete používat API funkce,
použijte objekt FileSystemObject a metodu GetSpecialFolder , která vrátí požadovanou
cestu. Vymazání všech souborů ve složce temp by mohlo vypadat např. takto:
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Kill fso.GetSpecialFolder(2) & "\*.*"
|
|
11/2000 |
3 |
Volání funkcí a procedur |
V tabulce (v databázi) mám seznam funkcí a procedur. Na jejich základě bych chtěl spouštět skutečné funkce a procedury
uložené v nějakém modulu. Je tohle vůbec ve VB možné? |
Jak zavolat nějakou funkci přímo se nám bohužel zjistit nepodařilo. Ale je možné to trochu obejít. VB obsahuje příkaz
CallByName , který umí volat metody nějakého objektu podle názvu. Pokud si ty svoje funkce a procedury vložíte
do nějaké třídy, můžete potom pomocí tohoto příkazu volat požadovaně metody. Budete-li mít např. třídu Class1 a v ní
metodu Metoda1, zavoláte ji takto:
Dim q As New Class1, met As String
met="Metoda1"
CallByName q, met, VbMethod, ..... (..... = parametry metody)
|
|
11/2000 |
3 |
Soubory |
Potřebuji na disku vyhledat určitý soubor a nevím jak na to. |
Můžete použít příkaz Dir a procházení celého disku si zařídit sám. Nebo, pokud jde opravdu jen o jednoduché
vyhledání, použijte API funkci SearchTreeForFile . Její první parametr určuje, odkud se bude hledat (např.
"C:\"), druhý název hledaného souboru a třetí je proměnná, do které se uloží název včetně cesty v případě jeho nalezení
(v takovém případě vrací funkce hodnotu 1). Deklarace funkce vypadá takto:
Declare Function SearchTreeForFile Lib "imagehlp.dll" _
(ByVal sRootPath As String, ByVal InputPathName As String, _
ByVal OutputPathBuffer As String) As Long
|
|
11/2000 |
3 |
Myš |
Potřebuji ze svého programu hýbat kurzorem myši a dále bych chtěl uživateli zakázat pohyb myší
mimo formulář aplikace. |
Pokud chcete hýbat s kurzorem myši, musíte použít API funkci a to např. SetCursorPos . Má pouze
dva parametry a to souřadnice x a y, kam se má kurzor umístit (v pixelech). Zabránění pohybu myši mimo
formulář není problém, ale opět musíte použít API funkce. Funkce GetWindowRect
naplní proměnnou typu RECT souřadnicemi formuláře a jejím předáním funkci ClipCursor
zamezíte pohybu mimo tuto zadanou oblast.
Dim r As RECT
GetWindowRect Form1.hWnd, r
ClipCursor r
|
|
11/2000 |
3 |
Databáze |
Z vašich seriálů jsem se dozvěděl jak odstranit záznam z databáze. Já bych ale potřeboval vymazat všechny záznamy
najednou. Jde to? Také by mě zajímalo jak udělat "refresh" u ovládacího prvku MSFlexGrid, nepodařilo se mi to jinak, než zavřít a otevřít formulář s prvkem. |
Všechny záznamy tabulky smažete naráz nejlépe pomocí SQL příkazu DELETE.
myDb.Execute "DELETE * FROM Tabulka1"
U FlexGridu je důležité jak jej používáte, ale pokud pouze na prohlížení s tím, že editace se provádí v jiných
prvcích, pomůže vám metoda Refresh prvku Data, na který je FlexGrid připojen.
|
|
11/2000 |
3 |
FTP |
Potřebuji stáhnout nějaký soubor z FTP serveru. Např. zadám ftp://ftp.xy.cz//help.zip a stáhnu jej na
disk C. |
Stáhnutí souboru z FTP serveru je nejjednodušší pomocí prvku Inet. Nastavíte vlastnost Protocol ,
URL , UserName a Password a pomocí metody Execute můžete
zadávat některé FTP příkazy.
Inet1.Protocol = icFTP
Inet1.URL = "ftp.xy.cz"
Inet1.UserName = "uzivatel"
Inet1.Password = "heslo"
Inet1.Execute , "GET help.zip C:\help.zip"
|
|
11/2000 |
3 |
Soubory |
Jak se dá udělat kontrolní součet (CRC32) souboru? |
Pan Milan Slovák nalezl na webu komponentu, která přesně tohle umí. Stáhnout si ji můžete ze stránek
www.sirocco.force9.co.uk,
welcome.to/sirocco nebo
www.preface.co.uk. Komponenta je zdarma a můžete
ji použít ve Visual Basicu verze 4 (32 bitová verze), 5 i 6. |
|
11/2000 |
3 |
Tisk |
Ve 4. dílu seriálu byla popsána možnost vytvoření tiskového výstupu
z tabulky dat vytvořené pomocí FlexGridu. Nevíte prosím jak na to v DBGridu. |
DBGrid žádnou podobnou možnost jako FlexGrid nemá, proto z něj není příliš výhodné tisknout. Pokud chcete tisknout
data, která obsahuje, raději vytiskněte jeho obsah procházením objektu Recordset prvku Data, na který
je DBGrid připojen, normálně pomocí metody Print objektu Printer . Zjednodušeně nějak takto:
Do While Not Data1.Recordset.EOF
radek = Data1.Recordset!jmeno & chr(9) & Data1.Recordset!prijmeni & vbCrLf
Printer.Print radek
Data1.Recordset.MoveNext
Loop
Printer.EndDoc
|
|
12/2000 |
3 |
Modem |
Na stisk tlačítka potřebuji vytočit telefonní číslo na modemu. Můžete mi prosím poradit? |
Pro práci s modemem je ve VB komponenta MSComm. Její použití je dobře popsáno v MSDN, takže stručně asi takto:
MSComm1.CommPort = 2 'seriový port, na kterém je připojen modem
MSComm1.Settings = "9600,N,8,1 'nastavení portu (blíže viz. MSDN)
MSComm1.PortOpen = True 'Otevření portu
MSComm1.Output = "ATDT" & cislo & vbCrLf 'Vytočení čísla
|
|
12/2000 |
3 |
MSFlexGrid |
Nevím jakou funkcí zajistit aby se v tabulce MSFlexGrid po přechodu na vzdálenou pozici (např. po funkci vyhledávání)
příslušný řádek zobrazil. Vždy se pouze označí, ale je třeba ještě zajistit "přerolování" seznamu.
V prvku ListView toto zajišťuje metoda EnsureVisible objektu ListItem . |
Chcete-li zobrazit řádek, který je mimo viditelnou oblast (je někde dole nebo nahoře), použijte vlastnost TopRow .
Stačí jí zadat číslo řádku. Pokud chcete to samé se sloupci, použijte LeftCol . |
|
12/2000 |
3 |
Hudba |
Chci přehrávat WAV soubory pomocí API funkce sndPlaySound, ale nefunguje mi to. Chybu to žádnou
nevypíše, ale ani nehraje. Deklaraci funkce jsem použil z API Text Vieweru. Kód vypadá takto:
Dim x As Long
x = sndPlaySound("c:\windows\media\tada.wav", SND_LOOP)
|
Chyba je v parametru flags funkce sndPlaySound . Používáte konstantu
SND_LOOP , která zapříčiní, že je soubor přehráván pořád dokola. Proto musíte ještě přidat
konstantu SND_ASYNC , která způsobí, že kód pokračuje hned dále aniž by čekal na ukončení přehrávání
(jinak by se program zastavil, čemuž se funkce brání, proto nic nepřehraje).
Dim x As Long
x = sndPlaySound("c:\windows\media\tada.wav", SND_LOOP + SND_ASYNC)
|
|
12/2000 |