Tato funkce slouží nejen pro zjišťování některých systémových hodnot, ale i jejich nastavení.
Kompletní popis funkce se nachází v MSDN.
Nás však bude zajímat zjištění viditelné plochy Windows bez otravného TaskBaru či zda jsou okna animována.
Nejdříve hlavička programu:
LOCAL liErr,lcRect,liWidth,liHeight,liOut #DEFINE SPI_GETWORKAREA 48 #DEFINE SPI_GETANIMATION 72 #DEFINE SPI_GETDRAGFULLWINDOWS 38 #DEFINE SPI_SETDRAGFULLWINDOWS 37
Pro zjištění velikosti plochy bez Taskbaru se použije konstanta SPI_GETWORKAREA. Druhý parametr je vždy 0. Třetí parametr je odkaz na strukturu RECT do které se naplní informace o počáteční pozici a velikosti. Čtvrtý parametr je vždy 0. Jelikož struktura RECT obsahuje pozice horního levého a pravého rohu a dolního levého a pravého rohu, musejí se hodnoty příslušné hodnoty odečíst.
DECLARE INTEGER SystemParametersInfo IN User32.dll INTEGER,INTEGER,STRING @,INTEGER lcRect=SPACE(16) && Nadimenzování řetězce pro naplnění struktury liErr=SystemParametersInfo(SPI_GETWORKAREA,0,@lcRect,0) && Vrať velikost plochy bez TaskBaru IF liErr>0 && Neselhalo volání funkce liWidth=C4ToL(SUBS(lcRect,9,4))-C4ToL(LEFT(lcRect,4)) liHeight=C4ToL(SUBS(lcRect,13,4))-C4ToL(SUBS(lcRect,5,4)) ?'Velikost plochy: Šířka=',liWidth,'Výška:',liHeight ENDIF
Pro zjištění zda jsou okna animována (při maximalizaci a minimalizaci) se použije konstanta SPI_GETANIMATION. Druhý parametr je vždy velikost struktury ANIMATIONINFO. Třetí parametr je odkaz na strukturu ANIMATIONINFO do které se naplní příznak animace. Čtvrtý parametr je vždy 0.
lcRect=IToC4(8)+' ' && Nadimenzování řetězce pro naplnění struktury liErr=SystemParametersInfo(SPI_GETANIMATION,8,@lcRect,0) && Zjisti příznak animace oken IF liErr>0 && Neselhalo volání funkce ?'Animace oken:',IIF(C4ToI(SUBS(lcRect,5,4))>=1,'Ano','Ne') ENDIF
Příznak posunu celých oken je funkční pouze pro Win95 Plus Pack! nebo vyšší a NT 3.51 nebo vyšší. Jelikož jako třetí parametr se musí poslat odkazem proměnná na číslo, musí se API funkce předeklarovat. Druhý a čtvrtý parametr je 0. Pro zjištění příznaku se použije konstanta SPI_GETDRAGFULLWINDOWS a pro nastavení SPI_SETDRAGFULLWINDOWS.
DECLARE INTEGER SystemParametersInfo IN User32.dll INTEGER,INTEGER,INTEGER @,INTEGER liOut=0 liErr=SystemParametersInfo(SPI_GETDRAGFULLWINDOWS,0,@liOut,0) && Zjisti příznak posouvání oken IF liErr>0 && Neselhalo volání funkce ?'Posouvání celých oken:',IIF(liOut>=1,'Ano','Ne') IF liOut=0 && Bylo-li to zakázáno liOut=1 && Pak to povol liErr=SystemParametersInfo(SPI_SETDRAGFULLWINDOWS,0,@liOut,0) IF liErr>0 && Neselhalo volání funkce ?'Nastaveno posouvání celých oken...' ENDIF ELSE && Bylo-li to povoleno liOut=0 && Pak to zakaž liErr=SystemParametersInfo(SPI_SETDRAGFULLWINDOWS,0,@liOut,0) IF liErr>0 && Neselhalo volání funkce ?'Zrušeno posouvání celých oken...' ENDIF ENDIF ENDIFA zbylé procedury:
*********************************************************************************************** * PROCEDURE C4ToI(lcInt) && Převede číslo v řetězcovém tvaru WINAPI 32 bitů - signed na číslo RETURN ASC(LEFT(lcInt,1))+; ASC(SUBS(lcInt,2,1))*256+; ASC(SUBS(lcInt,3,1))*65536+; ASC(RIGHT(lcInt,1))*256*65536 && vrať číslo v decimálním tvaru *********************************************************************************************** * PROCEDURE C4ToL(lcLong) && Převede číslo v řetězcovém tvaru WINAPI 32 bitů na číslo LOCAL liVal liVal=ASC(LEFT(lcLong,1))+; ASC(SUBS(lcLong,2,1))*256+; ASC(SUBS(lcLong,3,1))*65536+; ASC(RIGHT(lcLong,1))*256*65536 RETURN IIF(liVal<=0x7FFFFFFF,liVal,liVal-(0xFFFFFFFF+1)) *********************************************************************************************** * PROCEDURE IToC4(liVal) && Převede číslo na 4 bajtový řetězec LOCAL lcVal,lii lii=INT(liVal/256) && Vyděl 256 lcVal=CHR(liVal-lii*256) && Převeď rozdíl na znak a přičti ho liVal=lii && Zapiš novou hodnotu pro převod lii=INT(liVal/256) && Vyděl 256 lcVal=lcVal+CHR(liVal-lii*256) liVal=lii && Zapiš novou hodnotu pro převod lii=INT(liVal/256) && Vyděl 256 lcVal=lcVal+CHR(liVal-lii*256) liVal=lii && Zapiš novou hodnotu pro převod lii=INT(liVal/256) && Vyděl 256 RETURN lcVal+CHR(liVal-lii*256) && Převeď rozdíl na znak a přičti ho
Nejčastější je předávání více hodnot do formuláře a jejich navrácení zpět.
Někdy je nutné znát parametry již v události Load() nebo ještě dříve (události DataEnvironmentu).
Formulář sice podporuje převzetí parametrů, ale až v události Init() v době, kdy jsou inicializovány všechny objekty.
Optimální by bylo, pokud by se do formuláře (nejen formuláře, ale i programu nebo procedury) předával jen jeden parametr typu Objekt.
Proč má být jako parametr objekt? Protože se přes něj dá poslat více hodnot, včetně odkazů na další objekty, a také navrátit další hodnoty získané v závislosti na zadaných parametrech.
Aby jsme se vyhli vytváření PUBLIC či PRIVATE proměnné, tak si vytvoříme třídu _StackParameters, která bude fungovat jako zásobník parametrů.
Instanci třídy ( s názvem "SP") přidáme do objektu _Screen pomocí metody AddObject().
Třída má metodu Put() pro uložení parametru do zásobníku a metodu Get() pro výběr parametru ze zásobníku.
Je to naprogramované ve stylu LIFO - Last In, First Out (Poslední dovnitř, První ven).
Jako parametr nám poslouží instance třídy _Param, která má vlastnosti First a Second pro předání hodnot do formuláře a vlastnost OK pro navrácení příznaku, zda byl formulář ukončen tlačítkem OK.
Před zavoláním formuláře (nebo procedury) se pomocí metody Put() uloží parametr do zásobníku.
Pak se zavolá formulář, který v události Load() vybere pomocí metody Get() parametr ze zásobníku a uloží si ho do vlastnosti Param.
V události Init() pak přebere hodnoty z vlastností parameru do vlastností Value textboxů.
Navrácení hodnot zajišťuje tlačítko OK, které uloží hodnoty z vlastností Value textboxů do příslušných vlastností parametru.
Dále pak nastaví vlastnost OK na .T. - příznak ukončení dialogu (potvrzení uživatelem) - a ukončí formulář.
Poznámka:
Formulář můžete zavolat kdykoliv, ale mějte na paměti, že pokud je z události When() nebo Valid() volán další formulář, pak při zavolání metody SetFocus() - třeba v události Init() formuláře - Visual FoxPro vyhlásí chybu.
Následující zdrojový kód předvádí výše uvedenou teorii od vytvoření zásobníku parametrů až po zpracování hodnot zadaných uživatelem.
************************************************************************ * Hlavní program LOCAL loPar,loForm * Přidej objekt do objektu _Screen, vyhneme se tím deklaraci PUBLIC proměnné _Screen.AddObject("SP","_StackParameters") loPar=CREATEOBJECT("_Param") && Vytvoř parametr pro předání hodnot loPar.Second=loPar.Second+" A" _Screen.SP.Put(@loPar) && Ulož parametr do zásobníku loForm=CREATEOBJECT("_dlgForm") && Vytvoř instanci formuláře pro zadání hodnot * Zde však může být * DO FORM dglForm LINKED NAME loForm * * Takže je úplně jedno, zda je formulář definován jako třída v PRG souboru * nebo VCX knihovně, či jako čistý formulář. * V této chvíli jsou již hodnoty ve formuláři načteny do objektů =MESSAGEBOX(loForm.txtSecond.Value) loForm.Show() && Zobraz formulář * Jelikož je formulář modální, zpracování událostí se zastaví, * dokud formulář není uvolněn z paměti, nebo není skryt. IF loPar.OK && Dialog byl potvrzen =MESSAGEBOX("První hodnota:"+CHR(9)+loPar.First+; CHR(13)+CHR(10)+; "Druhá hodnota:"+CHR(9)+loPar.Second) ELSE * Dialog nebyl potvrzen ENDIF _Screen.RemoveObject("SP") && Odstraň Zásobník parametrů RELE loForm,loPar ************************************************************************ * #DEFINE _MaxCount 65000 && Maximální počet buňek v interní matici DEFINE CLASS _StackParameters AS custom && Definice třídy zásobníku parametrů PROTECTED ARRAY aPar(_MaxCount) PROTECTED iCount iCount=0 && Počet řádků matice aPar PROCEDURE Put(luPar) && Uloží parametr do zásobníku This.iCount=This.iCount+1 && Inkrementuj čítač DIME This.aPar(This.iCount) && Předimenzuj matici This.aPar(This.iCount)=luPar && Ulož parametr do zásobníku ENDPROC PROCEDURE Get() && Vybere poslední parametr ze zásobníku LOCAl luPar IF This.iCount>0 && Pokud v zásobníku něco je luPar=This.aPar(This.iCount) && Vyber parametr ze zásobníku This.iCount=This.iCount-1 && Dekrementuj čítač IF This.iCount>0 DIME This.aPar(This.iCount) && Předimenzuj matici ENDIF ELSE luPar=.NULL. ENDIF RETURN luPar && Vrať hodnotu ENDPROC ENDDEFINE ************************************************************************ * DEFINE CLASS _Param AS custom && Definice třídy pro předání parametrů OK=.F. && Příznak o potvrzení dialogu First = "First" && První hodnota Second = "Second" && Druhá hodnota ENDDEFINE ************************************************** *-- Form: form1 (x:\ptriky\quas40_2.scx) *-- ParentClass: form *-- BaseClass: form *-- Time Stamp: 04/18/02 03:11:01 PM * DEFINE CLASS _dlgForm AS form Top = 0 Left = 0 Height = 145 Width = 272 DoCreate = .T. BorderStyle = 2 Caption = "Form1" WindowType = 1 *-- Na tuto vlastnost se nalinkuje vybraný parametr ze zásobníku param = .NULL. Name = "dlgForm" ADD OBJECT txtfirst AS textbox WITH ; Height = 23, ; Left = 105, ; Top = 24, ; Width = 100, ; Name = "txtFirst" ADD OBJECT txtsecond AS textbox WITH ; Height = 23, ; Left = 105, ; Top = 51, ; Width = 100, ; Name = "txtSecond" ADD OBJECT cmdok AS commandbutton WITH ; Top = 96, ; Left = 21, ; Height = 27, ; Width = 84, ; Caption = "OK", ; Default = .T., ; Name = "cmdOK" ADD OBJECT cmdcancel AS commandbutton WITH ; Top = 96, ; Left = 146, ; Height = 27, ; Width = 84, ; Cancel = .T., ; Caption = "Zrušit", ; Name = "cmdCancel" ADD OBJECT lblfirst AS label WITH ; Caption = "První hodnota:", ; Height = 17, ; Left = 15, ; Top = 29, ; Width = 80, ; Name = "lblFirst" ADD OBJECT lblsecond AS label WITH ; Caption = "Druhá hodnota:", ; Height = 17, ; Left = 14, ; Top = 55, ; Width = 87, ; Name = "lblSecond" PROCEDURE Load This.Param=_Screen.SP.Get() && Vyber parametr ze zásobníku * V zde se můžou již nastavit některé věci pro formulář, * ale hodnoty do objektů se musí nastavit až v události Init() * (protože objekty txtFirst a txtSecond neexistují). * Výjimku tvoří případy, kdy je formulář vytvořen na základě tídy s vnořenýma objektama ENDPROC PROCEDURE Init * Nyní přetáhni hodnoty z parametru do objektů na formuláři IF !ISNULL(This.Param) && Pokud byl parametr předán Thisform.txtFirst.Value=Thisform.Param.First Thisform.txtSecond.Value=Thisform.Param.Second ENDIF ENDPROC PROCEDURE cmdok.Click IF !ISNULL(Thisform.Param) && Pokud byl parametr předán Thisform.Param.OK=.T. && Nastav potvrzení dialogu Thisform.Param.First=Thisform.txtFirst.Value && A ulož hodnoty do vlastností Thisform.Param.Second=Thisform.txtSecond.Value ENDIF Thisform.Release() && Ukonči formulář ENDPROC PROCEDURE cmdcancel.Click Thisform.Release() && Ukonči formulář ENDPROC ENDDEFINE * *-- EndDefine: form1 **************************************************