home *** CD-ROM | disk | FTP | other *** search
/ Programming Tool Box / SIMS_2.iso / info / api / apidoc.txt next >
Text File  |  1995-02-27  |  54KB  |  1,284 lines

  1. Inhaltsverzeichnis
  2.  
  3. Programmverknⁿpfung    3
  4. Fensterhandling    3
  5. Fenstertitel des aktiven Fensters ermitteln    4
  6. Schwebendes Fenster    4
  7. Mauszeiger auf Bereich beschrΣnken    4
  8. Mauszeigerposition bestimmen    5
  9. Mauszeiger auf bestimmte Position setzen    5
  10. Warten vor dem Weiterfahren    6
  11. Prⁿfen auf DOS-Anwendung    6
  12. Mehrfachstart einer Anwendung unterbinden    6
  13. Feststellen, wie ein Steuerelement den Focus erhalten hat    7
  14. Selektion in einem Kombinationsfeld    7
  15. Programmgesteuertes Booten    8
  16. Screenshot    8
  17. MS-DOS-Text in Windows-Text umwandeln    11
  18. Hoch-/Querformat-Umstellung per Programm    11
  19. Drucker umschalten    12
  20. Containerobjekte zwischen Formularen verschieben    14
  21. Shell modal    16
  22. Mauszeiger verstecken    16
  23. Schriften vertikal ausgeben    17
  24. Hotkey    19
  25. Debug-Fenster l÷schen    20
  26. Inhalt Beispieldiskette    22
  27.  
  28.  
  29. Index der benutzten API-Funktionen
  30.  
  31.  
  32.  
  33. A
  34. AnsiToOem    12
  35. B
  36. BitBlt    10
  37. C
  38. ClipCursorClear    5
  39. ClipCursorRect    5
  40. CreateFontIndirect    19
  41. D
  42. DeleteObject    19
  43. E
  44. ExitWindows    9
  45. F
  46. FindExecutable    4
  47. G
  48. GetActiveWindow    5; 8
  49. GetAsyncKeyState    8; 21
  50. GetClientRect    19
  51. GetCursorPos    6
  52. GetDC    10
  53. GetDesktopWindow    10
  54. GetModuleUsage    16
  55. GetProfileString    13; 15
  56. GetTextMetrics    19
  57. GetTickCount    7
  58. GetWindowRect    5; 10
  59. GetWindowTask    7
  60. GetWindowText    5
  61. I
  62. IsWinOldApTask    7
  63. L
  64. LockWindowUpdate    4
  65. O
  66. OemToAnsi    12
  67. P
  68. PostMessageByString    14
  69. R
  70. ReleaseDC    10
  71. ResetDC    13
  72. S
  73. SelectObject    19
  74. SendMessage    8; 21
  75. SetCursorPos    6
  76. SetParent    15
  77. SetWindowPos    5
  78. ShowCursor    17
  79. SwitchToThisWindow    7
  80. T
  81. TextOut    19
  82. W
  83. WriteProfileString    14
  84.  
  85.  
  86.  
  87. Quellenangabe:
  88. Visual Basic Programmer's Guide to the Windows API,Daniel Appleman, Copyright (c) 1993 by Ziff-Davis Press
  89.  
  90.  
  91. Programmverknⁿpfung
  92. Im Dateimanager k÷nnen Sie sogenannte Verknⁿpfungen vornehmen. Dabei bestimmen Sie, welches Programm gestartet 
  93. werden soll und die angegebene Datei laden soll, wenn die entsprechende Datei ge÷ffnet wird. Die Verknⁿpfung erfolgt 
  94. jeweils ⁿber die Dateiendung. Bei einem Doppelklick auf eine Datei mit der Endung .TXT wird standardmΣssig das 
  95. Programm NOTEPAD.EXE gestartet und die angeklickte Datei geladen. Windows bietet nun ein API, um anhand eines 
  96. Dateinamens den Programmnamen des verknⁿpften ausfⁿhrbaren Programmes ausfindig zu machen. ▄ber die folgende 
  97. Funktion k÷nnen Sie den zugeh÷rigen Dateinamen in Erfahrung bringen:
  98.  
  99. Declare Function FindExecutable% Lib "shell.dll" (ByVal lpszFile$, ByVal lpszDir$, 
  100. ByVal lpszResult$)
  101.  
  102. Function GetLinkedAppName (pfad$)
  103.   Dim i%
  104.   Dim Resultat$
  105.   Resultat$ = String$(256, " ")
  106.   i% = FindExecutable%(pfad$, "", Resultat$)
  107.   GetLinkedAppName = Left$(Resultat$, InStr(Resultat$ + Chr$(0), Chr$(0)) - 1)
  108. End Function
  109.  
  110. Damit sind Sie in der Lage, die Dateimanager-FunktionalitΣt nachzubilden. Erzeugen Sie eine DateiListBox und fⁿgen Sie 
  111. im Click-Ereignis folgenden Code ein:
  112.  
  113. Sub File1_DblClick ()
  114.   Dim tmp$, i%
  115.   tmp$ = File1.Path
  116.   If Right$(tmp$, 1) <> "\" Then tmp$ = tmp$ + "\"
  117.   On Error Resume Next
  118.   i% = Shell(Trim$(GetLinkedAppName(tmp$ + File1) + " " + tmp$ + File1), 1)
  119.   If Err Then
  120.     MsgBox "Diese Datei ist mit keiner Anwendung verknⁿpft", 48, "Fehler"
  121.     Exit Sub
  122.   End If
  123. End Sub
  124.  
  125. Fensterhandling
  126. Fenster einfrieren. Manchmal kann es wⁿnschenswert sein, den Aufbau eines Fensters zu verstecken. Werden z.B. sehr 
  127. viele Steuerelemente auf einer Form neu positioniert, so kann man den Aufbau mitverfolgen. Ausserdem dauert es recht 
  128. lange. Frieren Sie das Fenster vor dem Aufbau ein und geben es erst nach dem Aufbau wieder frei, so gewinnen Sie Zeit 
  129. und erhalten erst noch ein sch÷neres Finish. Mit dieser Funktion kann auch das Fⁿllen von Listboxen beschleunigt werden.
  130.  
  131. Declare Function LockWindowUpdate Lib äUserô (ByVal hWnd As Integer) As Integer
  132.  
  133. Function Freeze(hWnd as Integer)
  134.   Dim Ret%
  135.   Ret% = LockWindowUpdate(hWnd%)
  136. End Function
  137.  
  138. Function UnFreeze(hWnd%)
  139.   Dim Ret% 
  140.   Ret% = LockWindowUpdate(0)
  141. End Function
  142.  
  143. Nach dem Aufruf von MeltWindow sollten Sie dafⁿr sorgen, dass alle betroffenen Fenster neu gezeichnet werden. Um z.B. 
  144. die aktive Form einzufrieren, benutzen Sie den Aufruf i% = Freeze((Me.hWnd)). Die doppelten runden Klammern werden 
  145. ben÷tigt fⁿr die Typumwandlung. Um eine Listbox einzufrieren, benutzen Sie den Aufruf i% = Freeze ((List1. hWnd)).
  146.  
  147.  
  148. Fenstertitel des aktiven Fensters ermitteln
  149. Mittels folgender Funktion k÷nnen Sie den Fenstertitel des gerade aktiven Fensters ermitteln. Dies ist besonders dann 
  150. interessant, wenn es sich nicht um ein eigenes Fenster handelt. Mit der Routine AppActivate k÷nnen Sie das Fenster zu 
  151. einem spΣteren Zeitpunkt wieder aktivieren.
  152.  
  153. Declare Function GetActiveWindow Lib "User" () As Integer
  154.  
  155. Declare Function GetWindowText Lib "User" (ByVal hWnd As Integer, ByVal lpString As 
  156. String, ByVal aint As Integer) As Integer
  157.  
  158. Function AktFensterTitel$ ()
  159.   Dim Titel$, laenge%
  160.   Titel$ = Space$(255)
  161.   laenge% = GetWindowText(GetActiveWindow(), Titel$, 255)
  162.   AktFensterTitel$ = Left$(Titel$, laenge%)
  163. End Function
  164.  
  165. Schwebendes Fenster
  166. Manchmal m÷chte man verhindern, dass ein Fenster durch andere Fenster verdeckt werden kann. Diesen Effekt kann man 
  167. mittels eines API-Aufrufs erzielen. Die folgende Routine schaltet das aktuelle Fenster (Me) um, so dass es immer im 
  168. Vordergrund bleibt. Ein erneuter Aufruf der Routine schaltet das aktuelle Fenster wieder in den Normalzustand um.
  169.  
  170. Declare Sub SetWindowPos Lib "User" (Byval hWnd as integer, Byval hWndInsertAfter 
  171. as Integer, Byval X as Integer, Byval Y as Integer, Byval cx as Integer, Byval cy 
  172. as Integer, Byval wFlags as Integer)
  173.  
  174. Sub SwitchOnTopMode ()
  175.   Static Modus%
  176.   If Not Modus% Then
  177.     SetWindowPos form1.hWnd, -1, 0, 0, 0, 0, &H50 'Immer sichtbar
  178.   Else
  179.     SetWindowPos form1.hWnd, -2, 0, 0, 0, 0, &H50 'Normalzustand
  180.   End If
  181.   Modus% = Not Modus%
  182. End Sub
  183.  
  184. Mauszeiger auf Bereich beschrΣnken
  185. Mittels API-Funktionen kann man den Bereich, der mit dem Mauszeiger erreichbar sein soll, einschrΣnken. Wollen Sie 
  186. z.B. erreichen, dass der Anwender nicht mit dem Mauszeiger aus einem Bildfeld herausfahren kann, k÷nnen Sie dies 
  187. folgendermassen tun.
  188.  
  189. Type RECT
  190.     left As Integer
  191.     top As Integer
  192.     right As Integer
  193.     bottom As Integer
  194. End Type
  195.  
  196. Declare Sub ClipCursorRect Lib "User" Alias "ClipCursor" (lpRect As RECT)
  197.  
  198. Declare Sub ClipCursorClear Lib "User" Alias "ClipCursor" (ByVal lpRect&)
  199.  
  200. Declare Sub GetWindowRect Lib "User" (ByVal hWnd%, lpRect As RECT)
  201.  
  202. Sub LimitCursor (hWnd%)
  203.   Dim r As RECT
  204.   GetWindowRect hWnd%, r
  205.   ClipCursorRect r
  206. End Sub
  207.  
  208. Sub FreeCursor ()
  209.   ClipCursorClear 0
  210. End Sub
  211.  
  212. Um nun den Mauszeiger-Aktionsbereich festzulegen ⁿbergeben Sie der Funktion LimitCursor den Fensterhandle des 
  213. entsprechenden Bereichs. Bitte beachten Sie unbedingt, dass die Prozedur FreeCursor spΣtestens beim Verlassen des 
  214. Programmes aufgerufen wird, denn die Einstellung bleibt sonst auch nach demerlassen des Beispiel, um den Cursor auf die 
  215. aktuelle Form zu beschrΣnken: 
  216.  
  217. LimitCursor((me.hwnd))
  218.  
  219. Beispiel, um den Cursor auf das Bildfeld Picture1 zu beschrΣnken:
  220.  
  221. Limitcursor((picture1.hwnd))
  222.  
  223. Sie k÷nnen den Bereich, auf den Sie den Mauszeiger beschrΣnken m÷chten, auch ävon Handô bestimmen, indem Sie in der 
  224. Funktion LimitCursor statt die Funktion GetWindowRect aufzurufen direkt die entsprechenden Werte der Struktur RECT 
  225. setzen. Dabei mⁿssen Sie aber beachten, dass das API die X/Y-Koordinaten in Pixeln und relativ zum gesamten Bildschirm 
  226. erwartet.
  227.  
  228. Mauszeigerposition bestimmen
  229. Solange der Mauszeiger sich ⁿber einem Formular der eigenen Visual Basic Anwendung befindet, kann man anhand des 
  230. MouseMove-Ereignisses jeweils herausfinden, wo sich der Mauszeiger gerade befindet. Wird der Mauszeiger jedoch ⁿber 
  231. ein fremdes Programm oder ⁿber den Desktop bewegt, so kann man mit Visual Basic die aktuelle Position nicht mehr 
  232. herausfinden. Das Windows-API GetCursorPos hilft bei der L÷sung des Problems. Die folgende Prozedur liefert die X/Y-
  233. Position des Mauszeigers, egal, wo er sich gerade befindet. Da die Windows-APIs immer in Pixeln arbeiten, k÷nnen Sie 
  234. beim Aufruf der Routine ⁿber das Flag Twips% angeben, ob die Koordinaten in Twips (Twips% = True) oder in Pixeln 
  235. (Twips% = False) zurⁿckgegeben werden sollen.
  236.  
  237. Type POINTAPI
  238.     X As Integer
  239.     Y As Integer
  240. End Type
  241.  
  242. Declare Sub GetCursorPos Lib "User" (lpPoint As POINTAPI)
  243.  
  244. Sub GetMousePos (X%, Y%, Twips%)
  245.   Dim p As POINTAPI
  246.   GetCursorPos p
  247.   If Twips% Then
  248.     X% = p.X * screen.TwipsPerPixelX
  249.     Y% = p.Y * screen.TwipsPerPixelY
  250.   Else
  251.     X% = p.X
  252.     Y% = p.Y
  253.   End If
  254. End Sub
  255.  
  256. Mauszeiger auf bestimmte Position setzen
  257. Mit dem Windows-API SetCursorPos kann der Mauszeiger per Programm an einen bestimmten Ort auf dem Bildschirm 
  258. gesetzt werden. Wie bei API-Routinen ⁿblich, werden von SetCursorPos die X/Y-Koordinaten in Pixeln und nicht in Twips 
  259. erwartet. Die Position muss immer auf den ganzen Bildschirm bezogen angegeben werden. Die folgende Funktion 
  260. erm÷glicht nun die Positionierung, wobei zwischen Twix und Pixeln umgeschaltet werden kann wie bei der Funktion 
  261. GetMousePos.
  262.  
  263. Declare Sub SetCursorPos Lib "User" (ByVal X As Integer, ByVal Y As Integer)
  264. Sub SetMousePos (X%, Y%, Twips%)
  265.   Dim p As POINTAPI
  266.   If Twips% Then
  267.     p.X = X% / screen.TwipsPerPixelX
  268.     p.Y = Y% / screen.TwipsPerPixelY
  269.   Else
  270.     p.X = X%
  271.     p.Y = Y%
  272.   End If
  273.   SetCursorPos p.X, p.Y
  274. End Sub
  275.  
  276. Warten vor dem Weiterfahren
  277. In der Multitaskingumgebung von Windows wird es direkt schwierig, ein Programm dazu anzuhalten, eine bestimmte Zeit 
  278. lang einfach zu warten, bevor es weiter abgearbeitet wird. Mit der folgenden Routine k÷nnen Sie Ihr Programm dazu 
  279. veranlassen, eine bestimmte Zeit in Millisekunden zu warten. Dazu wird das API GetTickCount benutzt, das die Anzahl 
  280. Millisekunden liefert, seit der die aktuelle Windows-Sitzung lΣuft. ▄ber einen ZΣhler wird die M÷glichkeit einer 
  281. Endlosschleife vermieden. Diese Massnahme schrΣnkt jedoch die maximale Wartezeit ein.
  282.  
  283. Declare Function GetTickCount Lib "User" () As Long
  284.  
  285. Sub Wait (Millisekunden%)
  286.   Dim zaehler&
  287.   Dim StartZeit As Long, EndZeit As Long
  288.   StartZeit = GetTickCount()
  289.   Do
  290.     zaehler& = zaehler& + 1
  291.     If (GetTickCount() - StartZeit) > Millisekunden% Then Exit Do
  292.   Loop Until zaehler& = 60000
  293. End Sub
  294.  
  295. Prⁿfen auf DOS-Anwendung
  296. Mit der folgenden Funktion k÷nnen Sie ein Fenster daraufhin untersuchen, ob es eine DOS-Anwendung enthΣlt oder nicht.
  297.  
  298. Declare Function GetWindowTask Lib "User" (ByVal hWnd As Integer) As Integer
  299.  
  300. Declare Function IsWinOldApTask Lib "Kernel" (ByVal hTask As Integer) As Integer
  301.  
  302. Function IsDOS (hWnd As Integer) As Integer
  303.   IsDOS = IsWinOldApTask(GetWindowTask(hWnd))
  304. End Function
  305.  
  306. Mehrfachstart einer Anwendung unterbinden
  307. Oft m÷chte man verhindern, dass die eigene Anwendung mehrfach gestartet werden kann. Dies selbst ist eigentlich kein 
  308. Problem; schon etwas kniffliger wird es, wenn man die Erst-Instanz des Programmes aktivieren m÷chte, bevor man die 
  309. zusΣtzlich gestartete Anwendung wieder verlΣsst. Folgende Routine l÷st das Problem. Die Routine sollte entweder in der 
  310. Startroutine Sub Main oder im Load-Ereignis der Startform aufgerufen werden. Das benutzte Windows-API geh÷rt zu den 
  311. nicht dokumentierten APIs.
  312.  
  313. Declare Sub SwitchToThisWindow Lib "user" (ByVal hWnd%, ByVal StateNormal%)
  314.  
  315. Sub AppActivatePreviousInstance ()
  316.   Dim ThisAppTitle$
  317.   If App.PrevInstance Then
  318.     ThisAppTitle$ = App.Title
  319.     App.Title = ""
  320.     On Error Resume Next
  321.     AppActivate ThisAppTitle$
  322.     SwitchToThisWindow GetActiveWindow(), True
  323.     End
  324.   End If
  325. End Sub
  326.  
  327. Feststellen, wie ein Steuerelement den Focus erhalten hat
  328. Um festzustellen, ob ein Steuerelement den Focus durch die BetΣtigung der TAB-Taste, durch eine ALT-
  329. Tastenkombination (Kurztaste), einen Mausklick oder eine Programmanweisung erhalten hat, kann direkt im GotFocus-
  330. Ereignis des entsprechenden Steuerelementes folgender Code verwendet werden:
  331.  
  332. Declare Function GetAsyncKeyState Lib "User" (ByVal vKey As Integer) As Integer
  333. Global Const ON_TAB = 1
  334. Global Const ON_ALT = 2
  335. Global Const ON_MOUSE = 3
  336. Global Const ON_ELSE = 4
  337.  
  338. Function GotFocusON ()
  339.   Const KEY_TAB = &H9
  340.   Const KEY_MENU = &H12
  341.   Const KEY_LBUTTON = &H1
  342.   If GetAsyncKeyState(KEY_TAB) = &H8001 Then
  343.     GotFocusON = ON_TAB
  344.   ElseIf GetAsyncKeyState(KEY_MENU) = &H8001 Then
  345.     GotFocusON = ON_ALT
  346.   ElseIf GetAsyncKeyState(KEY_LBUTTON) = &H8001 Then
  347.     GotFocusON = ON_MOUSE
  348.   Else
  349.     GotFocusON = ON_ELSE
  350.   End If
  351. End Function
  352.  
  353. Tip: Diese Funktion kann Ihnen gute Dienste leisten, wenn Sie nach dem allgemein verwendeten Muster von Windows 
  354. arbeiten m÷chten und beim Anspringen eines Textfeldes mittels TAB den Inhalt des Textfeldes markieren m÷chten. Dies 
  355. k÷nnen Sie innerhalb des GotFocus-Ereignisses des entsprechenden Textfeldes folgendermassen erreichen (hier am Beispiel 
  356. des Textfeldes Text1):
  357.  
  358. Sub Text1_GotFocus ()
  359.   If GotFocusON() <> ON_MOUSE Then
  360.     Text1.SelStart = 0
  361.     Text1.SelLength = Len(Text1.Text)
  362.   End If
  363. End Sub
  364.  
  365. Selektion in einem Kombinationsfeld
  366. Vor allem in Datenbankanwendungen muss man oft ein Kombinationsfeld oder ein Listenfeld nach einem bestimmten 
  367. Eintrag durchsuchen und diesen zum aktuellen Eintrag machen. Dies lΣsst sich zwar gut mit Visual Basic selbst l÷sen, doch 
  368. dauert das  Durchsuchen der Listbox nach einem bestimmten Eintrag recht lange. Die folgende Routine liefert eine 
  369. wesentlich schnellere L÷sung ⁿber das Windows-API:
  370.  
  371. Declare Function SendMessage Lib "User" (ByVal hWnd As Integer, ByVal wMsg As 
  372. Integer, ByVal wParam As Integer, lParam As Any) As Long
  373.  
  374. Global Const WM_USER = &H400
  375. Global Const LB_SELECTSTRING = (WM_USER + 13)
  376.  
  377. Sub SelectListItem (lst As Control, Idx As String)
  378.   Dim i As Integer
  379.   i = SendMessage(lst.hWnd, LB_SELECTSTRING, -1, ByVal Idx)
  380. End Sub
  381.  
  382. Angenommen, Sie haben ein Kombinationsfeld mit dem Namen Combo1, das unter anderem den Eintrag Test enthΣlt, so 
  383. lautet der Aufruf: SelectListItem Combo1, äTestô
  384. System ⁿber WIN.INI-─nderung informieren. Wenn eine Anwendung unter Windows ─nderungen in der WIN.INI-Datei 
  385. vornimmt, so weiss vor einem Neustart von Windows keine andere Anwendung von den ─nderungen. Windows stellt nun 
  386. ein API zur Verfⁿgung, mittels dem alle Anwendungen dazu veranlasst werden k÷nnen, die EintrΣge der WIN. INI neu 
  387. einzulesen. 
  388.  
  389. Const HWND_BROADCAST = &HFFFF
  390. Const WM_WININICHANGE = &H1A
  391.  
  392. Declare Function SendMessage Lib "User" (ByVal hWnd As Integer, ByVal wMsg As 
  393. Integer, ByVal wParam As Integer, lParam As Any) As Long
  394.  
  395. Sub wininichangenotify ()
  396.   Dim i&
  397.   i& = SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, 0)
  398. End Sub
  399.  
  400. Programmgesteuertes Booten
  401. In Setuproutinen oder bei Werkzeugen zum Umstellen von Grafikaufl÷sungen ist es oft n÷tig, Windows neu zu starten, 
  402. damit vorgenommene ─nderungen in Kraft treten. Manchmal ist es sogar unabdingbar, den Computer einem Warmstart zu 
  403. unterziehen, um Treiberkonfigurationen oder Σhnliches zu aktivieren. Die folgende Routine l÷st das Problem durch ein 
  404. Windows-API: 
  405.  
  406. Declare Function ExitWindows Lib "User" (ByVal RestartCode As Long,ByVal 
  407. DOSReturnCode As Integer) As Integer
  408.  
  409. Sub ExitWin (ByVal nExitOption As Integer)
  410.   Dim n As Integer
  411.   n = MsgBox("Hiermit beenden Sie Ihre Windows-Sitzung", 65, "Windows beenden")
  412.   If n = 2 Then Exit Sub 'Benutzer wΣhlte Nein
  413.   Select Case nExitOption
  414.     Case 1
  415.       n = ExitWindows(67, 0) 'Warmstart des Computers
  416.     Case 2
  417.       n = ExitWindows(66, 0) 'Windows neu starten
  418.     Case 3
  419.       n = ExitWindows(0, 0) 'Windows verlassen
  420.   End Select
  421. End Sub
  422.  
  423. Folgende Aufrufe fⁿhren zum entsprechenden Ziel:
  424.  
  425. Warmstart des Computers : ExitWin 1
  426. Windows neu starten : ExitWin 2
  427. Windows verlassen : ExitWin 3
  428. Screenshot
  429. Im folgenden sollen zwei ab und zu auftauchende Probleml÷sungen fⁿr das Entwicklerleben aufgezeigt werden. Das erste 
  430. Problem ist das ⁿbernehmen eines beliebigen Fensterinhaltes oder des gesamten Bildschirmes in ein Bildfeld von Visual 
  431. Basic. Das zweite ist das Ausdrucken des Inhaltes eines Bildfeldes. Mit diesen beiden Funktionen zusammen erstellen wir 
  432. dann ein Werkzeug, mit dem Bildschirm-Schnappschⁿsse erstellt werden k÷nnen.
  433. Um den Inhalt eines Fensters in ein Bildfeld zu ⁿbernehmen, ben÷tigt man den Handle des entsprechenden Fensters (ⁿber 
  434. das API GetDesktopWindow) erhΣlt man den Handle des gesamten Bildschirms). Anhand dieses Handles bestimmt man 
  435. den Quell-Devicekontext. Den Ziel-Devicekontext erhΣlt man ⁿber die hDC-Eigenschaft des Bildfeldes. Mittels dem API 
  436. BitBlt werden nun aus dem Quell-Devicekontext die Daten in den Ziel-Devicekontext ⁿbertragen. Damit alle Daten im 
  437. Bildfeld Platz haben, wird es vorgΣngig noch auf die korrekte Gr÷sse gebracht. Darauf bleibt nur noch den Quell-
  438. Devicekontext wieder freizugeben. Damit enthΣlt das Bildfeld den gewⁿnschten Fensterinhalt. Es ist zu beachten, dass die 
  439. Eigenschaft AutoRedraw des Bildfeldes auf True gesetzt ist!
  440.  
  441. Type lrect
  442.   Left As Integer
  443.   Top As Integer
  444.   right As Integer
  445.   bottom As Integer
  446. End Type
  447.  
  448. Declare Function GetDesktopWindow Lib "user" () As Integer
  449. Declare Function GetDC Lib "user" (ByVal hWnd%) As Integer
  450. Declare Function BitBlt Lib "GDI" (ByVal hDestDC%, ByVal X%, ByVal Y%, ByVal 
  451. nWidth%, ByVal nHeight%, ByVal hScrDC%, ByVal XSrc%, ByVal YScr%, ByVal dwRop&) As 
  452. Integer
  453. Declare Function ReleaseDC Lib "User" (ByVal hW_nd%, ByVal hDC%) As Integer
  454. Declare Sub GetWindowRect Lib "User" (ByVal hWnd%, lpRect As lrect)
  455.  
  456. Sub Screenshot (pic As PictureBox, hwndSrc%)
  457.   Dim hSrcDC%
  458.   Dim XSrc%, YSrc%
  459.   Dim nWidth%, nHeight%
  460.   Dim X%, Y%
  461.   Dim winSize As lrect
  462.   Dim hDestDC%
  463.   Dim dwRop&
  464.   Dim suc%, dmy%
  465.     XSrc% = 0
  466.   YSrc% = 0
  467.   X% = 0
  468.   Y% = 0
  469.   pic.Top = 0
  470.   pic.Left = 0
  471.     hSrcDC% = GetDC(hwndSrc%)
  472.   GetWindowRect hwndSrc%, winSize
  473.   nWidth% = winSize.right
  474.   nHeight% = winSize.bottom
  475.   hDestDC% = pic.hDC
  476.   pic.Width = nWidth% * screen.TwipsPerPixelX
  477.   pic.Height = nHeight% * screen.TwipsPerPixelY
  478.   dwRop& = &HCC0020
  479.   suc% = BitBlt(hDestDC%, X%, Y%, nWidth%, nHeight%, hSrcDC%, XSrc%, YSrc%, dwRop&)
  480.   dmy% = ReleaseDC(hwndSrc%, hSrcDC%)
  481. End Sub
  482.  
  483. Nun k÷nnen wir bereits mit dem Aufruf äScreenshot me.picture1, hWnd%ô das durch den Handle hWnd% bestimmte 
  484. Fenster in das Bildfeld picture1 laden.
  485.  
  486. Der Ausdruck eines Bildfeldes gestaltet sich so, dass zunΣchst die Eigenschaft ScaleMode sowohl des Bildfeldes als auch 
  487. des Druckers auf äPixelô gesetzt wird, weil das API StretchBlt Pixel-Koordinaten verlangt. Darauf wird ein Speicherbereich 
  488. bereitgestellt, um das Bild fⁿr die Kopieraktion in den kompatiblen Devicekontext vorzubereiten. ▄ber das API 
  489. SelectObject wird das Objekt gespeichert. Mittels der Funktion StretchBlt wird nun das Bitmap vom Speicherbereich zum 
  490. Drucker kopiert. Danach wird der Speicherbereich wieder freigegeben (Zuerst selektiert und dann gel÷scht). Die folgende 
  491. Routine erledigt diese Aufgabe:
  492.  
  493. Declare Function CreateCompatibleDC% Lib "GDI" (ByVal hDC%)
  494. Declare Function SelectObject% Lib "GDI" (ByVal hDC%, ByVal hObject%)
  495. Declare Function StretchBlt% Lib "GDI" (ByVal hDC%, ByVal X%, ByVal Y%, ByVal 
  496. nWidth%, ByVal nHeight%, ByVal hSrcDC%, ByVal XSrc%, ByVal YSrc%, ByVal nSrcWidth%, 
  497. ByVal nSrcHeight%, ByVal dwRop&)
  498. Declare Function DeleteDC% Lib "GDI" (ByVal hDC%)
  499. Declare Function Escape% Lib "GDI" (ByVal hDC As Integer, ByVal nEscape As Integer, 
  500. ByVal nCount As Integer, LpInData As Any, LpOutData As Any)
  501.  
  502. Sub printPicture (pic As Control)
  503.   Dim hMemoryDC%
  504.   Dim hOldBitMap%
  505.   Dim ApiError%
  506.   Dim prWidth, prHeight
  507.   Const SRCCOPY = &HCC0020
  508.   Const NEWFRAME = 1
  509.   Const PIXEL = 3
  510.   screen.MousePointer = 11
  511.   pic.Picture = pic.Image
  512.   pic.ScaleMode = PIXEL
  513.   printer.ScaleMode = PIXEL
  514.   printer.Print " "
  515.   If (printer.ScaleWidth - pic.ScaleWidth) < (printer.ScaleHeight - 
  516. pic.ScaleHeight) Then
  517.     prWidth = printer.ScaleWidth
  518.     prHeight = printer.ScaleHeight * (pic.ScaleHeight / pic.ScaleWidth)
  519.   Else
  520.     prHeight = printer.ScaleHeight
  521.     prWidth = printer.ScaleWidth * (pic.ScaleHeight / pic.ScaleWidth)
  522.   End If
  523.   hMemoryDC% = CreateCompatibleDC (pic.hDC)
  524.   hOldBitMap% = SelectObject(hMemoryDC%, pic.Picture)
  525.   ApiError% = StretchBlt(printer.hDC, 0, 0, prWidth, prHeight, hMemoryDC%, 0, 0, 
  526. pic.ScaleWidth, pic.ScaleHeight, SRCCOPY)
  527.   hOldBitMap% = SelectObject(hMemoryDC%, hOldBitMap%)
  528.   ApiError% = DeleteDC(hMemoryDC%)
  529.   ' Falls der Ausdruck nicht erfolgt, so entfernen Sie das Hochkomma
  530.   ' in der folgenden Zeile!
  531.   'Debug.Print Escape(printer.hDC, NEWFRAME, 0, Null, Null)
  532.   printer.EndDoc
  533.   screen.MousePointer = 1
  534. End Sub
  535.  
  536. Nun ist es ein leichtes, unser Screenshot-Programm zu schreiben. Wir erzeugen eine Form die ein Bildfeld (Picture1) 
  537. enthΣlt, dessen AutoRedraw-Eigenschaft auf True und dessen Visible-Eigenschaft auf False gesetzt ist. Dann erstellen wir 
  538. noch eine SchaltflΣche (Command1) auf unserem Formular deren Caption-Eigenschaft wir auf äScreenshotô setzen. Die 
  539. Form k÷nnen wir so anpassen, dass sie genau dieselbe Gr÷sse wie die SchaltflΣche hat. In das Click-Ereignis der 
  540. SchaltflΣche schreiben wir nun noch folgenden Code:
  541.  
  542. Sub Command1_Click ()
  543.   Dim SrcHwnd%
  544.   Me.Visible = False
  545.   DoEvents
  546.   SrcHwnd% = GetDesktopWindow()
  547.   Screenshot Me.Picture1, SrcHwnd%
  548.   printPicture Me.Picture1
  549.   Me.Visible = True
  550. End Sub
  551.  
  552. Kompilieren Sie das Programm und starten Sie es ausserhalb der Visual Basic-Entwicklungsumgebung. Die Form sorgt 
  553. selbst dafⁿr, dass sie nicht auf dem Screenshot angezeigt wird.
  554. Andreas Grob ist Ing. HTL Inf. und arbeitet als Programmierer/Analytiker bei der Firma Neuro Media AG
  555.  
  556. MS-DOS-Text in Windows-Text umwandeln
  557. Der ANSI/ISO Zeichensatz von Windows weicht in den Zeichen ⁿber 127 stark vom PC-Zeichensatz ab. Dies erfahren 
  558. deutschsprachige Anwender sehr schmerzhaft weil vorallem die schon aus frⁿheren PC-Zeiten berⁿchtigten Umlaute wieder 
  559. fⁿr Schwierigkeiten sorgen. Ein mit dem DOS-Editor Edit verfasster deutscher Text artet recht schnell in einen 
  560. Hieroglyphen-Marathon aus. Zur Umwandlung bietet das Windows-API die Hand. Die Funktion OemToAnsi wandelt eine 
  561. ⁿbergbebene Zeichenkette vom PC-Zeichensatz in den ANSI/ISO Zeichensatz von Windows um, wΣhrend AnsiToOem die 
  562. Rⁿckumwandlung vornimmt. Beide Funktionen ben÷tigen zwei Parameter wovon der erste die umzuwandelnde 
  563. Zeichenkette und der zweite die Zielzeichenkette ist. Wie bei APIs mit Zeichenketten ⁿblich muss die Zielzeichenkette mit 
  564. der zurⁿckerwarteten Anzahl Zeichen gefⁿllt sein, weil APIs nicht auf das Speichermanagement von Visual Basic zugreifen 
  565. und einfach voraussetzen, dass der entsprechende Speicherplatz fⁿr die Zeichenkette zur Verfⁿgung steht. Das folgende 
  566. allgemeine Modul erm÷glicht die Umwandlung.
  567.  
  568. Declare Function AnsiToOem Lib "Keyboard" (ByVal lpAnsiStr As String, ByVal 
  569. lpOemStr As String) As Integer
  570. Declare Function OemToAnsi Lib "Keyboard" (ByVal lpOemStr As String, ByVal 
  571. lpAnsiStr As String) As Integer
  572.  
  573. Function AnsiZuOem(Quelltext$) As String
  574.   Dim i%, Res$
  575.   Res$ = String$(Len(Quelltext$), " ")
  576.   i% = AnsiToOem(Quelltext$, Res$)
  577.   AnsiZuOem = Res$
  578. End Function
  579.  
  580. Function OemZuAnsi(Quelltext$) As String
  581.   Dim i%, Res$
  582.   Res$ = String$(Len(Quelltext$), " ")
  583.   i% = OemToAnsi(Quelltext$, Res$)
  584.   OemZuAnsi = Res$
  585. End Function
  586.  
  587. Hoch-/Querformat-Umstellung per Programm
  588. Die einfachste M÷glichkeit, den Drucker von Hoch- auf Querformat umzustellen ist die, es dem Benutzer zu ⁿberlassen. 
  589. ▄ber den Standarddialog um den Drucker zu konfigurieren kann der Benutzer beliebige Druckereinstellungen selbst 
  590. vornehmen. Um diese M÷glichkeit zu nutzen muss man lediglich ⁿber das Menⁿ File/Add File die Datei CMDIALOG.VBX 
  591. einbinden, ein Common Dialog Steuerelement auf einem Formular erstellen und dessen Action-Eigenschaft bei Bedarf  auf 
  592. 5 (Printerdialog) setzen.
  593. Leider hat dies nun aber auch Nachteile:
  594. - Die Wiederherstellung der ursprⁿnglichen Druckerkonfiguration ist nicht m÷glich.
  595. - Die Einstellung wirkt sich auf alle Programme aus, die den Standarddrucker benutzen.
  596. - Der Benutzer muss die Einstellung jedesmal manuell vornehmen.
  597. Auf der Suche nach einem Weg, der oben genannte Nachteile nicht aufweist, stolperte ich im API -Dschungel ⁿber die 
  598. Funktion ResetDC. Diese Funktion erlaubt es gezielt auf die Druckerkonfiguration Einfluss zu nehmen, ohne dass der 
  599. Benutzer hinzugezogen werden mⁿsste. Ausserdem bietet es folgende Vorteile:
  600. - Die Umstellung kann von einer Seite zur anderen innerhalb desselben Dokumentes erfolgen.
  601. - Die Umstellung gilt nur bis zum Ende des aktuellen Dokumentes (EndDoc).
  602. - Die Umstellung wirkt sich nicht auf andere Programme aus.
  603. Ich habe ein Modul mit zwei Routinen zusammengestellt, das die Umstellung des Druckers auf Hoch- rsp. auf Querformat 
  604. erm÷glicht. Um es einzugeben ÷ffnen Sie zuerst ein neues Modul und definieren im Deklarationsteil folgenden Typ:
  605.  
  606. Type DEVMODE    ' 68 Bytes
  607.     dmDeviceName As String * 32
  608.     dmSpecVersion As Integer
  609.     dmDriverVersion As Integer
  610.     dmSize As Integer
  611.     dmDriverExtra As Integer
  612.     dmFields As Long
  613.     dmOrientation As Integer
  614.     dmpapersize As Integer
  615.     dmPaperLength As Integer
  616.     dmPaperWidth As Integer
  617.     dmScale As Integer
  618.     dmCopies As Integer
  619.     dmdefaultsource As Integer
  620.     dmPrintQuality As Integer
  621.     dmColor As Integer
  622.     dmDuplex As Integer
  623.     dmYResolution As Integer
  624.     dmTTOption As Integer
  625. End Type
  626.  
  627. Diese Struktur nimmt die Konfiguration des Druckers auf. Dabei nimmt die Variable dmFields eine Sonderstellung ein, 
  628. denn ⁿber diese Variable wird festgelegt, welche Einstellungen der Struktur berⁿcksichtigt werden sollen. Dies erm÷glicht 
  629. es einzelne Einstellungen vorzunehmen, ohne die fⁿr die restlichen Parameter ben÷tigten Werte zu kennen.
  630. Nun wird noch das API selbst deklariert:
  631.  
  632. Declare Function ResetDC% Lib "GDI" (ByVal hDC%, lpdm As DEVMODE)
  633.  
  634. Darauf geben Sie die beiden Prozeduren Hochformat und Querformat ein:
  635.  
  636. Sub Querformat ()
  637.   Dim dm As DEVMODE
  638.   Dim i%
  639.   dm.dmOrientation = 2 ' Setzt Querformat
  640.   dm.dmFields = dm.dmFields Or 1 ' Flag DM_ORIENTATION
  641.   i% = ResetDC%(printer.hDC, dm)
  642. End Sub
  643.  
  644. Sub Hochformat ()
  645.   Dim dm As DEVMODE
  646.   Dim i%
  647.   dm.dmOrientation = 1 ' Setzt Hochformat
  648.   dm.dmFields = dm.dmFields Or 1 ' Flag DM_ORIENTATION
  649.   i% = ResetDC%(printer.hDC, dm)
  650. End Sub
  651.  
  652. Nun k÷nnen Sie in Ihrem Programm durch Aufruf der entsprechenden Prozedur den Drucker temporΣr auf die gewⁿnschte 
  653. Papierorientation umstellen.
  654.  
  655. Drucker umschalten
  656. Manchmal kommt es vor, dass der geplagte Programmierer sich vor dem Problem sieht, von seinem Programm aus auf 
  657. einen anderen Drucker umzuschalten. Leider bietet Visual Basic nicht die Befehle Setz_Standarddrucker und 
  658. Lies_Standarddrucker. Also mⁿssen wir sie selbst schreiben. Zuerst noch ein Theorieblock der aber ganz kurz gehalten ist. 
  659. Der Standarddrucker wird durch den Eintrag Device in der Sektion [windows] der Datei WIN.INI spezifiziert. Will man 
  660. nun den Standarddrucker Σndern, so muss man diesen Eintrag Σndern und um die ─nderung zu aktivieren, muss dem 
  661. System noch bekanntgegeben werden, dass eine ─nderung stattgefunden hat.
  662. Die Drucker, die auf dem System installiert worden sind, befinden sich in der Datei WIN.INI in der Sektion [devices].
  663. In dem Programm das wir nun erstellen, sollen alle m÷glichen Drucker in einer Liste aufgefⁿhrt werden und durch 
  664. Auswahl des entsprechenden Druckers und Klick auf eine SchaltflΣche soll der Standarddrucker festgelegt werden.
  665. Erstellen Sie nun ein Formular das wie folgt aussieht:
  666.  
  667. Nun deklarieren Sie die ben÷tigten Windows API Funktionen im generellen Teil des Formulars:
  668.  
  669. ' Windows API Funktionen
  670. Declare Function GetProfileString Lib "Kernel" (ByVal AppName$, ByVal KeyName As 
  671. Any, ByVal Default$, ByVal ReturnedString$, ByVal nSize%)
  672. Declare Function WriteProfileString Lib "Kernel" (ByVal AppName$, ByVal KeyName$, 
  673. ByVal lpString$)
  674. Declare Function PostMessageByString Lib "User" Alias "PostMessage" (ByVal hWnd%, 
  675. ByVal wMsg%, ByVal wParam%, ByVal lParam$)
  676.  
  677. ' Windows API Konstanten
  678. Const HWND_BROADCAST = &HFFFF
  679. Const WM_WININICHANGE = &H1A
  680.  
  681. Das API GetProfileString liest aus der Datei WIN.INI den Wert des Topics in der gewⁿnschten Sektion aus wΣhrend 
  682. WriteProfileString den Wert entsprechend setzt. Das API PostMessageByString wird dazu benutzt, um das System ⁿber die 
  683. ─nderung der Datei WIN.INI zu informieren, sodass die Werte der angegebenen Sektion neu eingelesen werden.
  684. Nun erstellen wir die Funktion Lies_Standarddrucker, die uns den Wert des Topics device aus der Sektion [windows] der 
  685. Datei WIN.INI liefert:
  686.  
  687. Function Lies_Standarddrucker$ ()
  688.   Dim temp$, res%
  689.  
  690.   'Herausfinden welcher Drucker als Standarddrucker definiert ist
  691.   temp$ = String$(255, 0)
  692.   res% = GetProfileString("windows", "device", "", temp$, Len(temp$))
  693.   Lies_Standarddrucker$ = temp$
  694. End Function
  695.  
  696. Die Prozedur Setz_Standarddrucker setzt den Topic device aus der Sektion [windows] der Datei WIN.INI auf den 
  697. ⁿbergebenen Wert:
  698.  
  699. Sub Setz_Standarddrucker (Drucker$)
  700.   Dim res%
  701.   ' Neuen Defaultdrucker in die Win.INI schreiben und das System
  702.   ' ⁿber die ─nderung informieren
  703.   res% = WriteProfileString("windows", "device", Drucker$)
  704.   res% = PostMessageByString(HWND_BROADCAST, WM_WININICHANGE, 0, "windows")
  705. End Sub
  706.  
  707. Damit sind unsere neuen Befehle bereits fertig. Wir wollen nun die Liste der verfⁿgbaren Drucker in unsere Listbox List1 
  708. einlesen. Dies soll die Prozedur Lies_Druckerliste erledigen:
  709.  
  710. Sub Lies_Druckerliste (Druckerliste As ListBox)
  711.   Dim res%, Drucker$, temp$, Alle_Drucker$
  712.  
  713.   Druckerliste.clear
  714.   Alle_Drucker$ = String$(4096, 0)
  715.   res = GetProfileString("devices", 0&, "", Alle_Drucker$, Len(Alle_Drucker$))
  716.   If res <> 0 Then
  717.     Do
  718.       Drucker$ = Left$(Alle_Drucker$, InStr(Alle_Drucker$, Chr$(0)) - 1)
  719.       Alle_Drucker$ = Mid$(Alle_Drucker$, InStr(Alle_Drucker$, Chr$(0)) + 1)
  720.             
  721.       ' EintrΣge fⁿr den entsprechenden Drucker auslesen
  722.       temp$ = String$(255, 0)
  723.       res% = GetProfileString("devices", Drucker$, "", temp$, Len(temp$))
  724.       Druckerliste.AddItem Drucker$ + "," + temp$
  725.     Loop Until Left$(Alle_Drucker$, 1) = Chr$(0)
  726.   End If
  727. End Sub
  728.  
  729. Dadurch, dass in dem ersten Aufruf des APIÆs GetProfileString als zweiter Parameter der Wert 0& ⁿbergeben wird, liefert 
  730. das API alle vorhandenen Topics der angegebenen Sektion zurⁿck. Die einzelnen Topics sind jeweils durch ein CHR$(0) 
  731. voneinander getrennt. In der Schleife werden nun die einzelnen Werte der Topics in die ⁿbergebene Listbox abgefⁿllt.
  732. Nun mⁿssen wir dafⁿr sorgen, dass beim Progammstart die Prozedur Lies_Druckerliste ausgefⁿhrt wird. Ausserdem soll der 
  733. Standarddrucker angezeigt werden und die Liste auch auf den Standarddrucker positioniert werden:
  734.  
  735. Sub Form_Load ()
  736.   Dim i%
  737.  
  738.   Lies_Druckerliste list1
  739.   label2.Caption = Lies_Standarddrucker$()
  740.   For i% = 0 To list1.ListCount - 1
  741.     If list1.List(i%) = label2.Caption Then
  742.       list1.ListIndex = i%
  743.       Exit For
  744.     End If
  745.   Next i%
  746. End Sub
  747.  
  748. Zu guter Letzt schreiben wir im Click-Ereignis der SchaltflΣche folgenden Code:
  749.  
  750. Sub Command1_Click ()
  751.   
  752.   Setz_Standarddrucker (list1)
  753.   label2.Caption = Lies_Standarddrucker$()
  754. End Sub
  755.  
  756. Damit k÷nnen wir mit unserem Programm den Standarddrucker entsprechend der verfⁿgbaren Drucker selbst umstellen 
  757. und nach Herzenslust drucken.
  758.  
  759. Containerobjekte zwischen Formularen verschieben
  760. Eine Rosine im API-Kuchen von Windows stellt die Funktion SetParent dar. Mittels dieser Funktion kann man 
  761. Steuerelemente modularisieren. Visual Basic verfⁿgt ⁿber sogenannte Containerobjekte. Ein Containerobjekt ist ein 
  762. Steuerelement innerhalb dem man weitere Steuerelemente plazieren kann. Containerobjekte erkennt man daran, dass bei 
  763. dessen Veschiebung die darin enthaltenen Steuerelemente mit verschoben werden. So sind z.B. der Rahmen und das Picture 
  764. Containerobjekte. In Visual Basic sind Containerobjekte selbstΣndige Fenster mit eigenem Fensterhandle. Sie besitzen 
  765. ausserdem ein ⁿbergeordnetes Fenster (Parent), nΣmlich das Formular (auch ein Fenster) innerhalb dem sie sich befinden 
  766. rsp. angezeigt werden. Damit ist Endstation fⁿr Visual Basic. Nun kommt aber Windows zum Zug, denn es liefert ein API, 
  767. das es erm÷glicht festzulegen, welches Fenster das ⁿbergeordnete Fenster sein soll. Damit hat man eine M÷glichkeit 
  768. Containerobjekte zwischen Formularen zu verschieben und somit steht einer Modularisierung von Containerobjekten nichts 
  769. mehr im Weg.
  770. Als Beispiel fⁿr ein allgemein nutzbares Containerelement wollen wir eine Uhr erstellen, die immer im aktiven Formular 
  771. links oben angezeigt werden soll. Als Containerelement benutzen wir einen Rahmen.
  772. Erstellen Sie also in Visual Basic ein neues Projekt und plazieren Sie in der Form1 einen Rahmen (Frame1) in der linken 
  773. oberen Ecke. In diesem Rahmen erzeugen Sie ein Bezeichnungsfeld (Label1). Damit haben wir das Containerobjekt mit 
  774. seinem Inhalt erzeugt. Nun erstellen wir ein neues Modul und deklarieren im generellen Teil das API SetParent:
  775.  
  776. Declare Function SetParent% Lib "User" (ByVal hWndChild%, ByVal hWndNewParent%)
  777. Im gleichen Modul schreiben wir nun die Prozedur ZeigUhr, die nichts anderes tut, 
  778. als das ⁿbergebene Formular zum Parent des Containerobjektes Frame1 zu machen..
  779. Sub ZeigUhr (frm As Form)
  780.   Dim Res As Integer
  781.  
  782.   Res = SetParent(Form1.Frame1.hWnd, frm.hWnd)
  783. End Sub
  784.  
  785. Nun erzeugen Sie ein zweites Formular (Form2). Sobald dieses Formular aktiviert wird, so soll die Uhr auf diesem 
  786. Formular angezeigt werden. Also schreiben Sie fⁿr die Form2 folgende Ereignisprozedur:
  787.  
  788. Sub Form_Activate ()
  789.   ZeigUhr Me
  790. End Sub
  791.  
  792. Hier bleibt noch zu bemerken, dass das Schliessen eines Formulars, das nicht der echte Parent eines enthaltenen 
  793. Containerobjektes ist fatale Folgen hat. Deshalb muss das Formular Form2 noch mit folgender Ereignisprozedur ergΣnzt 
  794. werden, die dafⁿr sorgt, dass beim Entladen des Formulars das Containerobjekt wieder auf das richtige Formular gesetzt 
  795. wird.
  796.  
  797. Sub Form_Activate ()
  798.   ZeigUhr Me
  799. End Sub
  800.  
  801. Damit nun bei der Rⁿckkehr auf das erste Formular die Uhr wieder zurⁿckkehrt, schreiben Sie fⁿr das Formular Form1 
  802. dieselbe Ereignisprozedur Form_Activate wie fⁿr das Formular Form2:
  803.  
  804. Sub Form_Activate ()
  805.   ZeigUhr Me
  806. End Sub
  807.  
  808. Jetzt mⁿssen Sie noch dafⁿr sorgen, dass das zweite Formular angezeigt wird, z.B. indem Sie folgende Ereignisprozedur fⁿr 
  809. das Formular Form1 schreiben:
  810.  
  811. Sub Form_Load ()
  812.   Form2.Show
  813. End Sub
  814.  
  815. Nun fehlt uns nur noch unsere Uhr. Dazu erzeugen Sie auf dem Formular Form1 einen Zeitmesser (Timer1) und stellen 
  816. dessen Eigenschaft Interval auf 1000 (entspricht einer Sekunde). Fⁿr den Zeitmesser schreiben Sie folgende 
  817. Ereignisprozedur die dem Bezeichnungsfeld in unserem Containerobjekt die aktuelle Uhrzeit zuweist.
  818.  
  819. Sub Timer1_Timer ()
  820.   label1.Caption = Time
  821. End Sub
  822.  
  823. Beachten Sie hierbei, dass egal welches Fenster gerade das Parentfenster eines Containerobjektes ist, es immer nur ⁿber das 
  824. Formular in dem es zur Entwicklungszeit erstellt wurde angesprochen wird.
  825. Nun k÷nnen Sie das Programm starten und durch abwechselndes Anklicken der zwei Formen feststellen, wie die Uhr sich 
  826. immer im aktiven Formular befindet. Jedes weitere Formular, welches ebenfalls die Uhr darstellen soll muss einfach 
  827. dieselben Ereignisprozeduren enthalten wie unser Formular Form2.
  828. Damit steht einer allgemeinen Verwendung von Containerelementen nichts mehr im Weg. Es ist sogar denkbar eigene 
  829. Containerelemente in fremden Fenstern zu plazieren. Dazu mⁿsste lediglich der Handle des fremden Fensters bestimmt 
  830. werden...
  831.  
  832. Shell modal
  833. Ein sehr hΣufiges Problem fⁿr den Visual Basic Programmierer ist das Multitasking von Windows. Dies vor allem dann, 
  834. wenn es eigentlich unerwⁿnscht ist. M÷chte man z.B. mit Visual Basic ein Programm schreiben, das mittels dem MS-DOS-
  835. Programm PKZIP.EXE Dateien komprimieren, dann die Gr÷sse der komprimierten Datei bestimmen und falls die 
  836. DateilΣnge gr÷sser ist als eine Diskette in einem Meldungsfenster diesen Umstand anzeigen soll, dann ist das leider mit 
  837. Windows nicht so einfach zu realisieren. Man kann zwar PKZIP.EXE mit dem Befehl SHELL aufrufen, aber dann fΣhrt das 
  838. Programm weiter bevor PKZIP.EXE seine Arbeit beendet hat. 
  839. Das Ziel ist es nun dafⁿr zu sorgen, dass das aufrufende Programm auf den Abschluss des aufgerufenen Programmes wartet 
  840. bis es weiterfΣhrt wie etwa ein modales Dialogfenster.
  841. Um dies zu erreichen ben÷tigen wir das Windows-API GetModuleUsage. Dieses API liefert einen Wert zurⁿck, der aussagt 
  842. wie oft das spezifizierte Modul geladen wurde. Die Deklaration des APIÆs lautet:
  843.  
  844. Declare Function GetModuleUsage Lib "KERNEL" (ByVal InstanceID%) As Integer
  845.  
  846. Nun fehlt uns nur noch der omin÷se ▄bergabeparameter InstanceID%. Dabei handelt es sich um den Handle der das 
  847. entsprechende Modul spezifiziert. Unter einem Modul ist ⁿbrigens eine beliebige ausfⁿhrbare Datei oder dynamische 
  848. Linkbibliothek (DLL) zu verstehen. InstanceID% soll nun also unser aufgerufenes Programm spezifizieren. Nun ist es so, 
  849. dass der Visual Basic Befehl SHELL mit dem wir das Programm starten als Rⁿckgabewert gerade den Handle des 
  850. gestarteten Programmes liefert. Dadurch ben÷tigen wir kein weiteres API das uns den ben÷tigten Handle liefert. Die 
  851. folgende Prozedur dient als allgemeiner Ansatz das Problem zu l÷sen:
  852.  
  853. Sub ShellModal (Kommandozeile$)
  854.   Dim Temp%,InstanceID%
  855.   InstanceID% = Shell(Kommandozeile$, 3)
  856.   Do
  857.     Temp% = DoEvents()
  858.   Loop Until GetModuleUsage(InstanceID%) = 0
  859. End Sub
  860.  
  861. Das Programm erwartet als ▄bergabeparameter die Kommandozeile um das gewⁿnschte Programm zu starten. 
  862. SelbstverstΣndlich funktioniert das Programm nicht nur bei DOS-Programmen sondern auch bei Windows-Programmen. In 
  863. der Variablen InstanceID% wird der Modul-Handle des gestarteten Programmes gespeichert. In einer DoEvents-Schleife 
  864. wird darauf gewartet, dass der Rⁿckgabewert von GetModuleUsage 0 betrΣgt. Erst dann wird die Prozedur beendet.
  865.  
  866. Mauszeiger verstecken
  867. Windows bietet ein API um den Mauszeiger anzuzeigen oder zu verstecken. Manche Abstⁿrze von Programmen lassen 
  868. gleich auch den Mauszeiger verschwinden. Es bleibt nichts anderes ⁿbrig, als Windows zu beenden und wieder zu starten 
  869. um den Mauszeiger wieder anzuzeigen. Nicht so, wenn man ein Programm schreibt, welches den Mauszeiger wieder 
  870. einschaltet. Genauso kann es unter UmstΣnden erwⁿnscht sein, den Mauszeiger zu verstecken wie z.B. bei einem 
  871. Bildschirmschoner. Mit der folgenden Routine lassen sich beide Varianten realisieren.
  872.  
  873. Declare Function ShowCursor Lib "User" (ByVal bShow As Integer) As Integer
  874. Const Ein = True
  875. Const Aus = False
  876.  
  877. Sub Mauszeiger (Modus%)
  878.   Dim i%
  879.   i% = ShowCursor(Modus%)
  880. End Sub
  881.  
  882. Durch den Aufruf Mauscursor Ein kann nun der Mauszeiger eingeschaltet werden, mit Mauscursor Aus kann er 
  883. ausgeschaltet werden.
  884.  
  885.  
  886.  
  887. Schriften vertikal ausgeben
  888. Auch wenn man sich im allgemeinen nicht mit den komplizierten Ausgabemechanismen fⁿr Schriftarten unter Windows 
  889. auseinandersetzten m÷chte, kommt man manchmal gar nicht darum herum. Ich wollte ein Zeichenprogramm erstellen mit 
  890. einem vertikalen Lineal links. In den Programmen, die ich als Vorbild genommen hatte, war das Lineal vertikal beschriftet. 
  891. Visual Basic erm÷glicht standardmΣssig nur die horizontale Zeichenausgabe. Um trotzdem in der Lage zu sein, meinem 
  892. Lineal einen professionellen Touch zu geben, stⁿrzte ich mich in die Tiefen der Windows-APIs um Schriftarten vertikal 
  893. auszugeben.
  894. Dabei hatte ich zwei wichtige Erkenntnisse:
  895. - Rasterschriften k÷nnen nicht rotiert werden (Alle TrueType-Schriften k÷nnen rotiert werden)
  896. - Die FunktionalitΣt der Eigenschaft AutoRedraw von Bildfeldern muss speziell behandelt werden, da die Windows-APIs 
  897. ihre Informationen nicht automatisch in das von Visual Basic gespeicherte Bitmap ⁿbertragen.
  898. Ansonsten befolgte ich die Schritte eine Schriftart auszugeben, wie sie in der einschlΣgigen Fachliteratur beschrieben sind. 
  899. So zaubert man nach Schema F jede TrueType-Schrift in der gewⁿnschten Art und Weise auf den Bildschirm oder falls 
  900. gewⁿnscht auf den Drucker, wenn statt dem Bildfeld das Druckerobjekt Printer angegeben wird.
  901. Um die Schrift zu rotieren, ben÷tigt man nur die Strukturvariable lfEscapement aus der Struktur LOGFONT. Diese nimmt 
  902. den gewⁿnschten Winkel auf, um den die Schrift rotiert werden soll und zwar in 1/10  von 0 bis 3600. Um den Text 
  903. vertikal auszugeben, muss lfEscapement auf 900 gesetzt werden. Wichtig ist noch, dass die Ausgabekoordinaten sich auf 
  904. die linke obere Ecke des nicht rotierten Textes bezieht. Ist der Text jedoch um 90 Grad rotiert, so ist dies die Ecke links 
  905. unten!
  906. Damit kann der Text bereits vertikal ausgegeben werden. Ein Bildfeld, das ein Lineal enthΣlt, hat nun aber mit Vorteil die 
  907. Eigenschaft AutoRedraw eingeschaltet, um ein m÷glichst schnelles Bildschirmrollen zu erm÷glichen. Ist die Eigenschaft 
  908. AutoRedraw  true, dann werden alle ⁿber Visual Basic Methoden ausgegebenen Informationen in einen Zwischenspeicher 
  909. transferiert, und erst dann wird dieser in das Bildfeld ⁿbertragen. Da das API TextOut an diesem Mechanismus vorbeilΣuft 
  910. muss man sich eines Tricks bedienen, um die angezeigten Informationen in den Zwischenspeicher zu speichern. Bei einem 
  911. Bildfeld bezeichnet die Eigenschaft Image das sichtbare Bild und die Eigenschaft Picture das von Visual Basic 
  912. zwischengespeicherte Abbild. Indem nun die Eigenschaft Image der Eigenschaft Picture zugewiesen wird, wird das Abbild 
  913. entsprechend dem sichtbaren Bild aktualisiert.
  914. Mit dem folgenden allgemeinen Modul kann Text vertikal ausgegeben werden. Der Aufruf lautet wie folgt:
  915. WriteVertical (PicText as PictureBox, X!, Y!, Text$)
  916. Parameter:
  917. PicText: Bildfeld, in dem der Text ausgegeben werden soll
  918. X! : X-Koordinate der linken unteren Ecke des auszugebenden Textes
  919. Y! : Y-Koordinate der linken unteren Ecke des auszugebenden Textes
  920. Text$ : Text der vertikal ausgegeben werden soll
  921. Die Prozedur berⁿcksichtigt automatisch die Einstellung der AutoRedraw-Eigenschaft des ⁿbergebenen Bildfeldes.
  922.  
  923. Schritt fⁿr Schritt Anleitung:
  924.  
  925. Erstellen Sie ein neues Projekt und erzeugen Sie in der Form das Bildfeld Picture1, das den gewⁿnschten Text anzeigen 
  926. soll. Setzen Sie die Eigenschaft ScaleMode des Bildfeldes auf  Pixels (3) und wΣhlen Sie als FontName eine TrueType-
  927. Schriftart. Daneben erzeugen Sie eine SchaltflΣche Command1. Wenn diese SchaltflΣche angeklickt wird, soll der Text 
  928. Hallo in dem Bildfeld ausgegeben werden.
  929. Dazu schreiben Sie folgenden Code in die entsprechende Ereignisroutine der Form1:
  930.  
  931. Sub Command1_Click ()
  932.   WriteVertical picture1, 1, picture1.ScaleHeight - 1, "Hallo"
  933. End Sub
  934.  
  935. Dann erstellen Sie ein Modul und fⁿgen folgenden Code in das Modul ein (Tip: kopieren Sie die Konstanten, Typen und 
  936. Deklarationen aus der Hilfedatei WIN31API.HLP im Unterverzeichnis WINAPI von Visual Basic):
  937.  
  938. Global Const LF_FACESIZE = 32
  939.  
  940. Type TEXTMETRIC
  941.     tmHeight As Integer
  942.     tmAscent As Integer
  943.     tmDescent As Integer
  944.     tmInternalLeading As Integer
  945.     tmExternalLeading As Integer
  946.     tmAveCharWidth As Integer
  947.     tmMaxCharWidth As Integer
  948.     tmWeight As Integer
  949.     tmItalic As String * 1
  950.     tmUnderlined As String * 1
  951.     tmStruckOut As String * 1
  952.     tmFirstChar As String * 1
  953.     tmLastChar As String * 1
  954.     tmDefaultChar As String * 1
  955.     tmBreakChar As String * 1
  956.     tmPitchandFamily As String * 1
  957.     tmCharSet As String * 1
  958.     tmOverhang As Integer
  959.     tmDigitizedAspectX As Integer
  960.     tmDigitizedAspectY As Integer
  961. End Type
  962.  
  963. Type logfont
  964.     lfHeight As Integer
  965.     lfWidth As Integer
  966.     lfEscapement As Integer
  967.     lfOrientation As Integer
  968.     lfWeight As Integer
  969.     lfItalic As String * 1
  970.     lfUnderline As String * 1
  971.     lfStrikeOut As String * 1
  972.     lfCharSet As String * 1
  973.     lfOutPrecision As String * 1
  974.     lfClipPrecision As String * 1
  975.     lfQuality As String * 1
  976.     lfPitchandFamily As String * 1
  977.     lfFaceName As String * LF_FACESIZE
  978. End Type
  979.  
  980. Type rect
  981.     left As Integer
  982.     top As Integer
  983.     right As Integer
  984.     bottom As Integer
  985. End Type
  986.  
  987. Declare Function CreateFontIndirect Lib "GDI" (lpLogFont As logfont) As Integer
  988. Declare Function DeleteObject Lib "GDI" (ByVal hObject As Integer) As Integer
  989. Declare Sub GetClientRect Lib "User" (ByVal hWnd As Integer, lpRect As rect)
  990. Declare Function SelectObject Lib "GDI" (ByVal hDC As Integer, ByVal hObject As 
  991. Integer) As Integer
  992. Declare Function TextOut Lib "GDI" (ByVal hDC As Integer, ByVal X As Integer, ByVal 
  993. Y As Integer, ByVal lpString As String, ByVal nCount As Integer) As Integer
  994. Declare Function GetTextMetrics Lib "GDI" (ByVal hDC As Integer, lpMetrics As 
  995. TEXTMETRIC) As Integer
  996.  
  997. Sub WriteVertical (PicText As PictureBox, X!, Y!, Text$)
  998.     Dim tm As TEXTMETRIC
  999.     Dim r$
  1000.     Dim crlf$
  1001.     Dim oldfont%
  1002.     Dim tbuf As String * 80
  1003.     Dim FontToUse%
  1004.     Dim lf As LOGFONT
  1005.     Dim oldhdc%
  1006.     Dim rc As RECT
  1007.     Dim di%
  1008.     
  1009.     di% = GetTextMetrics(PicText.hDC, tm)
  1010.     crlf$ = Chr$(13) + Chr$(10)
  1011.     If FontToUse% <> 0 Then di% = DeleteObject(FontToUse%)
  1012.     lf.lfHeight = tm.tmHeight * 1.1
  1013.     lf.lfWidth = tm.tmAveCharWidth * .9
  1014.     lf.lfEscapement = 900
  1015.     lf.lfWeight = tm.tmWeight
  1016.     lf.lfItalic = tm.tmItalic
  1017.     lf.lfUnderline = tm.tmUnderlined
  1018.     lf.lfStrikeOut = tm.tmStruckOut
  1019.     lf.lfOutPrecision = Chr$(0)
  1020.     lf.lfClipPrecision = Chr$(0)
  1021.     lf.lfQuality = Chr$(0)
  1022.     lf.lfPitchAndFamily = tm.tmPitchAndFamily
  1023.     lf.lfCharSet = tm.tmCharSet
  1024.     lf.lfFaceName = PicText.FontName + Chr$(0)
  1025.     FontToUse% = CreateFontIndirect(lf)
  1026.     If FontToUse% = 0 Then Exit Sub
  1027.     oldhdc% = SelectObject(PicText.hDC, FontToUse%)
  1028.     GetClientRect PicText.hWnd, rc
  1029.     di% = TextOut(PicText.hDC, X!, Y!, (Text$ + Chr$(0)), Len(Text$))
  1030.     di% = SelectObject(PicText.hDC, oldhdc%)
  1031.     If FontToUse% <> 0 Then di% = DeleteObject(FontToUse%)
  1032.     If PicText.AutoRedraw Then PicText.Picture = PicText.Image
  1033.  
  1034. End Sub
  1035.  
  1036. Wenn Sie nun das Programm starten und auf die BefehlsschaltflΣche klicken wird im Bildfeld vertikal Hallo ausgegeben, 
  1037. vorausgesetzt die Eigenschaft FontName des Bildfeldes enthΣlt den Namen einer Vektorschrift (Rasterschriften k÷nnen 
  1038. nicht rotiert werden).
  1039.  
  1040. Hotkey
  1041. Es ist mit einem Visual Basic Programm sehr komfortabel m÷glich die Tastatur zu ⁿberwachen, solange das Programm den 
  1042. Focus besitzt. Aber wehe es sollen auch Tastendrⁿcke  abgefangen werden, wenn das Programm den Focus nicht hat. 
  1043. Angenommen es stellt sich das Problem, dass eine Visual Basic Adressverwaltung resident geladen ist und mittels der 
  1044. Tastenkombination Ctrl+A aufgerufen werden soll, wenn man z.B. in Write einen Brief erfasst, so hat man Mⁿhe dies mit 
  1045. Visual Basic Bordmitteln zu realisieren.
  1046. Hierbei hilft das Windows-API GetAsyncKeyState. Mit diesem API kann bestimmt werden, ob seit dem letzten Aufruf von 
  1047. GetAsyncKeyState eine bestimmte Taste gedrⁿckt worden ist, und ob diese Taste im Augenblick gerade noch gedrⁿckt ist. 
  1048. Die Definition des API lautet:
  1049. Declare Function GetAsyncKeyState Lib äUserô (ByVal vKey%)
  1050. Das API ben÷tigt als Parameter den virtuellen Tastenkode dessen Status ⁿberprⁿft werden soll. Die entsprechenden 
  1051. Konstanten  beginnen mit VK_... und Sie finden die Konstanten in der Hilfedatei win31api.hlp unter äGlobal Constantsô. 
  1052. Der Rⁿckgabewert des API hat das Bit 0 gesetzt, wenn die Taste seit dem letzten Aufruf von GetAsyncKeyState gedrⁿckt 
  1053. wurde und das Bit 15 ist gesetzt, wenn die Taste im Augenblick der Abfrage gedrⁿckt war.
  1054. Im folgenden Beispiel soll ein Formular per Hotkey falls es minimiert ist wieder ge÷ffnet werden und falls es unsichtbar ist 
  1055. wieder angezeigt werden. Mittels zwei Kombinationslisten kann der gewⁿnschte Hotkey ausgewΣhlt werden, wobei die 
  1056. Listen nur eine Auswahl der m÷glichen Tastenkodes enthalten. ▄ber ein Timer-Steuerelement wird alle 500 Millisekunden 
  1057. das API GetAsyncKeyState aufgerufen und falls die Tasten gedrⁿckt wurden das Formular angezeigt:
  1058.  
  1059. Erstellen Sie ein Formular das zwei Kombinationslisten Combo1 und Combo2 ,eine SchaltflΣche Command1 und einen 
  1060. Timer Timer1 enthΣlt, dessen Intervall z.B. auf 500 eingestellt ist  (siehe Bild 1).
  1061. Geben Sie nun das Listing 1 ein. 
  1062.  
  1063. Declare Function GetAsyncKeyState Lib "User" (ByVal vKey As Integer) As Integer
  1064.  
  1065. Sub Add2Combo (cmb As combobox, inhalt$, wert%)
  1066.   cmb.AddItem inhalt$
  1067.   cmb.itemdata(cmb.newindex) = wert%
  1068. End Sub
  1069.  
  1070. Sub Form_Load ()
  1071.   Dim i%
  1072.   Add2Combo Combo1, "(keine)", &H0
  1073.   Add2Combo Combo1, "Shift", &H10
  1074.   Add2Combo Combo1, "Ctrl", &H11
  1075.   Add2Combo Combo1, "Alt", &H12
  1076.   Combo1.ListIndex = 0
  1077.  
  1078.   For i% = Asc("A") To Asc("Z")
  1079.     Add2Combo Combo2, Chr$(i%), i%
  1080.   Next i%
  1081.   For i% = 1 To 24
  1082.     Add2Combo Combo2, "F" & Format$(i%), 111 + i%
  1083.   Next i%
  1084.   Combo2.ListIndex = 0
  1085. End Sub
  1086.  
  1087. Sub Timer1_Timer ()
  1088.   Dim ctrl%, taste%
  1089.   If Me.Combo1.ItemData(Me.Combo1.ListIndex) = 0 Then
  1090.     ctrl% = 1
  1091.   Else
  1092.     ctrl% = GetAsyncKeyState(Me.Combo1.ItemData(Me.Combo1.ListIndex))
  1093.   End If
  1094.   taste% = GetAsyncKeyState(Me.Combo2.ItemData(Me.Combo2.ListIndex))
  1095.   If ctrl% <> 0 And taste% <> 0 Then
  1096.     Me.Show
  1097.     If Me.WindowState = 1 Then
  1098.       Me.WindowState = 0
  1099.     End If
  1100.   End If
  1101. End Sub
  1102.  
  1103. Sub Command1_Click ()
  1104.   Me.Hide
  1105. End Sub
  1106.  
  1107. Debug-Fenster l÷schen
  1108. Wie komfortabel ist es doch ⁿber den Befehl Debug.Print Debugginginformationen im Debugfenster auszugeben. Doch 
  1109. nach ein zwei LΣufen steht man bald einmal vor dem Problem, welche Ausgaben zum vorhergehenden Lauf und welche 
  1110. zum aktuellen geh÷ren. Natⁿrlich kann man jedesmal vor Programmstart den Inhalt des Debugfensters markieren und mit 
  1111. der Deletetaste l÷schen. Doch wer denkt schon jedesmal daran. Also soll die Arbeit doch vom Programm ⁿbernommen 
  1112. werden! Die folgende kleine Routine ⁿbernimmt die Aufgabe. Wird sie z.B. im Form_Load-Ereignis aufgerufen, so l÷scht 
  1113. sie den gesamten Inhalt des Debugfensters.
  1114.  
  1115. Declare Function FindWindow Lib "User" (ByVal lpClassName As Any, ByVal 
  1116. lpWindowName As Any) As Integer
  1117. Declare Function SendMessage Lib "User" (ByVal hWnd As Integer, ByVal wMsg As 
  1118. Integer, ByVal wParam As Integer, lParam As Any) As Long
  1119. Declare Function GetWindow Lib "User" (ByVal hWnd%, ByVal wCmd%) As Integer
  1120.  
  1121. Sub Debug_Clear ()
  1122.   Dim hWndVB%, hWndDebug%, res%
  1123.   ' bestimmen des Handles des Debug-Fensters (Fensterklasse = OFEDT)
  1124.   hWndVB% = FindWindow("OFEDT", 0&)
  1125.   ' Wurde das Fenster nicht gefunden lΣuft das Programm nicht in der
  1126.   ' Entwicklungsumgebung
  1127.   If hWndVB% = 0 Then Exit Sub
  1128.   ' bestimmen des Handles des Kindfensters (Das Textfenster des Debug-Fensters)
  1129.   hWndDebug% = GetWindow(hWndVB%, 5)
  1130.   ' Wurde kein Fensterhandle gefunden, existiert das Debug-Fenster nicht
  1131.   If hWndDebug% = 0 Then Exit Sub
  1132.   ' Text des Debug-Fensters auf eine Nullzeichenkette setzen
  1133.   res% = SendMessage(hWndDebug%, &HC, 0, 0&)
  1134. End Sub
  1135.  
  1136.  
  1137.  
  1138. Inhalt Beispieldiskette
  1139.  
  1140.  
  1141. Verzeichnis    Beschreibung    API Funktion
  1142.  
  1143. 1. Anltng    Beschreibung der API Funktionen
  1144.  
  1145. 2. Bitblt    Grafische Anzeige von Bitmaps    BitBlt
  1146.         StretchBlt
  1147.  
  1148. 3. Clipreg    Bestimmte Bereiche in einer Form mit Grafik fⁿllen    SelectClipRgn
  1149.             GetClientRect
  1150.         CreateEllipticRgnIndirect
  1151.  
  1152. 4. Cursor    Cursorform auf Knopfdruck Σndern    GlobalLock
  1153.         GlobalUnLock
  1154.         CreateCursor
  1155.         GetWindowWord
  1156.         SetClassWord
  1157.         GetClassWord
  1158.         GetBitmapBits
  1159.  
  1160. 5. Devcont    Form oder Printer Context anzeigen    GetDeviceCaps
  1161.  
  1162. 6. Dragdrop    Beispiel von Drag and Drop    DragAcceptFiles
  1163.         PeekMessage
  1164.         DragQueryFile
  1165.         DragFinish
  1166.  
  1167. 5. Drucker2    Aktuellen Drucker wechseln    GetProfileString
  1168.         GetPrivateProfileString
  1169.         WriteProfileString
  1170.         WritePrivateProfileString
  1171.  
  1172. 6. Exeicon    Programme ⁿber VB Form ausfⁿhren    GetModuleUsage
  1173.  
  1174. 7.Fltask    Alle Objekte auf dem Bildschirm in Bewegung 
  1175.     bringen        GetWindow
  1176.         GetWindowText
  1177.         GetWindowTextLength
  1178.         GetDeviceCaps
  1179.         FindWindow
  1180.         MoveTo
  1181.         MoveWindow
  1182.  
  1183. 8. Font    Informationen ⁿber Schriftarten anzeigen    SetMapMode
  1184.         GetMapMode
  1185.  
  1186. 9. Log    Texteditor um kleinere Textdateien zu editieren    GetModuleFileName
  1187.         GetClassWord
  1188.         GetActiveWindow
  1189.         isWindow
  1190.         GetWindowTask
  1191.  
  1192. 10. Lstsuch    Schnelles suchen nach einem Eintrag 
  1193.     in einer List Box    SendMessage
  1194.         GetCurrentTime
  1195.  
  1196. 11. Maskdemo    Zwei Bitmaps ⁿbereinander in neuen Bereich
  1197.     kopieren    BitBlt
  1198.  
  1199.  
  1200. 12. Menu    Darstellen von Bitmaps in einem Menu    GetMenu
  1201.         GetsubMenu
  1202.         GetMenuItemID
  1203.         ModifyMenu
  1204.         GetMenuItemBitmaps
  1205.  
  1206. 13. Nomdi    Beispiel einer Toolbox die immer im 
  1207.     Vordergrund bleibt    SetParent
  1208.  
  1209. 14. Puzzle    Aus einem bestehenden Bitmap wird ein Puzzle
  1210.     erstellt    GetObjectAPI
  1211.         CreateDIBitmap
  1212.         CreatePatternBrush
  1213.         GetClientRect
  1214.         CreateCompatibleDC
  1215.         StretchBlt
  1216.         PatBlt
  1217.         SelectObject
  1218.  
  1219. 15 Q2\Drucker    Feststellen was fⁿr Drucker zur Verfⁿgung stehen
  1220.     und den Default wechseln    GetProfileString
  1221.         WriteProfileString
  1222.         PostMessageByString
  1223.  
  1224. 16 Q2\handle    Feststellen welche Windows Applikationen aktiv
  1225.     sind und Informationen ⁿber diese Applikationen
  1226.     anzeigen    GetParent
  1227.         GetWindow
  1228.         GetWindowWord
  1229.         FlashWindow
  1230.         GetModuleFileName
  1231.         GetClassName
  1232.         GetDeskTopWindow
  1233.             ShowWindow
  1234.         ApiSetFocus
  1235.  
  1236. 17 Q2\Point    Zeigt die Adresse einer Variablen im Speicher an    PointerToObject
  1237.         DeRefString
  1238.  
  1239. 18 Q3\Sysinfo    Liefert System Informationen    RemoveMenu
  1240.         GetVersion
  1241.         GetNumTasks
  1242.         GetFreeSpace
  1243.         GetCurrentTime
  1244.         GetSubMenu
  1245.         GetSystemMenu
  1246.         GetWinFlags
  1247.  
  1248. 19. Setparent    Bewegt ein Frame von einer Form in eine andere    SetParent
  1249.  
  1250. 20. Sysinfo    Zeigt System Informationen an    GetWinFlags
  1251.         GetFreeSystemResources
  1252.         GetFreeSpace
  1253.  
  1254. 21. Task    Anzeigen der aktiven Applikationen    GetWindow
  1255.         GetWindowText
  1256.         GetWindowTextLength
  1257.  
  1258. 22. Textvert    Schrift vertikal darstellen        DeleteObject
  1259.         CreateFontIndirect
  1260.         GetClientRect
  1261.         SelectObject
  1262.         TextOut
  1263.         GetTextMetrics
  1264.  
  1265. 23. Tools\Apix    Zusammenfassung aller API Funktionen    GetFocus
  1266.         SendMessage
  1267.  
  1268.  
  1269. 24. Top    Form die immer im Vordergrund bleibt    GetVersion
  1270.         SetWindowPos
  1271.  
  1272. 25. Waitdos    Dos Befehle ausfⁿhren    GetModuleUsage
  1273.  
  1274.  
  1275. Neuro Media AG    API Kurs    14. Dezember 1994
  1276.  
  1277.  
  1278.  
  1279.  
  1280.  
  1281. ( 01 715 43 33 / FAX: 01 715 43 40        Seite 1
  1282.  
  1283.  
  1284.