Visual Basic FAQ

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