Tipy, triky, hotline III

Tentokrát si ukážeme použití funkce GetSystemMetrics() či drobné fígle s formuláři (třeba předání parametrů).


Funkce GetSystemMetrics()

Tuto funkci lze použít například k zabezpečení aplikace před spuštěním v nouzovém režimu Windows, který není pro spouštění aplikace vhodný.

* definice konstant
#DEFINE SM_CLEANBOOT 67
#DEFINE SM_CXSCREEN   0
#DEFINE SM_CYSCREEN   1 
#DEFINE SM_MOUSEPR   19

LOCAL lnCLEANBOOT,llMOUSE,llKONEC
LOCAL lnCXSCREEN,lnCYSCREEN
* registrujeme funkci GetSystemMetrics()
DECLARE LONG GetSystemMetrics IN Win32API LONG Index 

* Vrací hodnotu podle způsobu spuštění Windows
lnCLEANBOOT = GetSystemMetrics( SM_CLEANBOOT)
* 0 = Normální start, 1 = nouzový, 2 = nouzový se sítí
llKONEC= ( lnCLEANBOOT <> 0)

Funkce GetSystemMetrics() vrací i některá další systémová nastavení:

* Vrací šířku a výšku primárního monitoru v pixelech *)
lnCXSCREEN = GetSystemMetrics(SM_CXSCREEN)
lnCYSCREEN = GetSystemMetrics(SM_CYSCREEN)

* Vrací nulu, pokud není instalována myš
llMouse = (GetSystemMetrics(SM_MOUSEPR)>0)

Další možnosti funkce GetSystemMetrics() najdete v nápovědě k Win32API.
Příspěvek zaslal pan Daniel Hořešovský (horesovsky@seznam.cz)


Práce s formuláři

Patrně nejčastější prací programátora ve VFP je práce s formuláři. V tomto článku si ukážeme několik problémů při práci s nimi a jejich řešení.

1. Předání parametrů formuláři

Předávat parametry mezi formuláři není žádný problém - stačí například v metodě Valid() **) textboxu Text1 použít syntaxi: DO FORM FormName WITH cParameterList

Jenže hodnoty předávaných parametrů se dozvíme až v události Thisform.Init(), což je někdy příliš pozdě (představte si třeba, že na základě těchto hodnot chcete vybrat data, která budete ještě dále složitě zpracovávat. ***)). Ale tento problém můžeme snadno obejít. Ukažme si tedy program, který napíšeme do Thisform.Load(). Hlavní „trik“ spočívá v tom, že během Loadu je aktivní formulář brán pořád ještě ten původní, ze kterého spouštíme současný.

LOCAL loActiveForm,lcObjString, lcProgram, lcOnError,llError,loCallingObject
IF TYPE('_Screen.ActiveForm.BaseClass') <> 'C'
   * tedy tento formulář není volán z jiného formuláře
   RETURN .T.
ENDIF
loActiveForm = _SCREEN.ACTIVEFORM  && zjistili jsme referenci na původní formulář
* zjistíme jméno hodnoty, odkud je volán formulář ****)
lcProgram = PROGRAM(IIF('03.'$VERSION() OR '05.'$VERSION(),LastLevel(),PROGRAM(-1))-1)
                                   && například 'FORM1.TEXT1.VALID'
lcObjString = SUBSTRC(lcProgram,AT_C('.',lcProgram)+1)   && 'TEXT1.VALID'
lcObjString = LEFTC(lcObjString,RATC('.',lcObjString)-1) && 'TEXT1'
lcOnError = ON('ERROR')
ON ERROR llError=.T.
loCallingObject = EVAL('loActiveForm.' + lcObjString) && zjistili jsme referenci na Text1
ON ERROR &lcOnError.
* teď si tedy můžeme uložit Text1.Value do vlastnosti Thisform.cFiltr
* a později ji použít třeba na nastavení filtru,…
Thisform.cFiltr = loCallingObject.Value

PROCEDURE LastLevel() && Vrátí aktuální vnoření z volané metody/procedury
LOCAL lii
lii=1
* Běhej ve smyčce tak dlouho, dokud je znám program/procedura/metoda
DO WHILE !EMPTY(PROGRAM(lii))
   lii=lii+1 && Inkrementuj čítač
ENDDO
RETURN lii-2
ENDPROC

2. Vrácení hodnot z formuláře uloženého v knihovně tříd VCX

Pro vrácení hodnoty z modálního formuláře se používá syntaxe: DO FORM FormNameTO VarName a příkaz RETURN … se píše do metody Unload().

Ale co si máme počít, pokud budeme mít formulář definovaný v knihovně tříd VCX? Ukažme si tedy, jak definovat třídu tak, aby uměla vrátit změněnou hodnotu. Hlavní „trik“ spočívá v tom, že během Initu zobrazíme formuláře pomocí metody Show(). Použijeme parametr 1 - formulář se přepne do režimu Modální, i když není nastavena vlastnost WindowType na hodnotu 2. Po ukončení tohoto modálního režimu ukončíme práci celého formuláře.

LOCAL lcPromenna
lcPromenna=1234
CREATEOBJ('VratHodnotu',@lcPromenna)
?lcPromenna

DEFINE CLASS VratHodnotu AS FORM
   AUTOCENTER = .T.
   WIDTH  = 200
   HEIGHT = 100
   CAPTION = 'Třída vrátí hodnotu'
   ADD OBJECT txt AS TEXTBOX ;
       WITH TOP=20, LEFT=50, ;
       WIDTH=100

   ADD OBJECT cmd AS COMMANDBUTTON ;
       WITH TOP=60, LEFT=50, ;
       HEIGHT=25, WIDTH=100, ;
       CAPTION = '\<Konec', ;
       DEFAULT = .T.

   FUNC cmd.CLICK
        THISFORM.HIDE
   ENDFUNC

   FUNC INIT(puHodnota)
        THIS.txt.ControlCource = 'puHodnota'
        THIS.SHOW(1) && přímo v Initu zobrazíme objekt, 1=jako modální formulář!
                     && jelikož se jedná o modální formulář, stojí se zde během práce s ním
        RETURN .F.   && jelikož jsme hotovi, nechceme aby formulář dál existoval
   ENDFUNC
ENDDEFINE

3. Spouštění formulářů uložených v EXE nebo APP

Představme si, že máme vytvořenou velkou aplikaci, která je rozdělena do několika menších EXE či APP. Jak spustit z jednoho EXE formulář, který je uložen ve druhém EXE či APP? Bohužel neexistuje žádná volba: DO FORM FormNameIN EXE … takže si musíme nějak poradit sami *****). Asi jediné možné řešení je vytvořit si ve druhém EXE malý prográmek (takzvaný Proxy), který nebude dělat nic jiného, než zpřístupňovat formuláře z tohoto EXE a APP. Jeho obsah bude:

LPARAMETERS pcForm
DO FORM &pcForm.

Z ostatních EXE a APP pak budeme tento Proxy volat pomocí: DO Proxy IN EXE WITH 'JmenoFormulare'

A to je vše. Mějte se krásně
Milan Kosina, kosina@vol.cz

Pozn. *) přepis.: Pokud však budete chtít zjistit velikost plochy bez TaskBaru, pak se musí použít funkce SystemParametersInfo(). Použití je popsáno v článku Paralelní tipy a triky
Pozn. **) přepis.: Určení co je metoda a co je událost je značně zmatené. Držme se tedy jednoho pravidla…
Advanced OOP with Visual FoxPro:
When an event occurs, VFP automatically fires a method that's associated with that event…
Don't confuse these methods with events. An event method is just a method that happens to the same name as the event, and it gets fired automatically when an event happens.


Událost je to co se událo nezávisle na našem programu (posláni zprávy mezi 2 objekty) a metoda je zapouzdřený kód který je vyvolán ať už výskytem události nebo volán přímo z programu. (Milan Kosina)
Pozn. ***) přepis.: Toto je vhodné jen pro předání jedné hodnoty, navíc někdy může být nepříjemné, aby jako zdroj parametrů byl nějaký editační prvek.
Jak na to, je popsáno v článku Paralelní tipy a triky
Pozn. ****) přepis.: Zde musel trochu upravit zdrojový kód tak, aby byl funkční i ve VFP 3.0 nebo VFP 5.0
Pozn. *****) přepis.: Ano, taková Proxy procedura je docela dobrá věc. Můžete mít Proxy proceduru na spuštění formuláře, další na spuštění programu/procedury a další na otevření tabulky. Nebo taky můžete mít jednu obecnou, která bude umožnovat spustit cokoliv a ještě předat dejme tomu až deset parametrů.