Windows

Windows

Detecting Win95 Vs W3.X
Getting large text from TClipboard
Long file names from Win95 DirListbox
Application.Title font color
Application to tile on windows desktop
Change wallpaper bitmap
Obtaining Windows Version
Creating and selecting palettes
Loading a listbox with program groups
System colors
Under Win95?
Knowing that Windows is exiting
Screen Saver Register
Hiding apps from taskbar
Reading from Registry
User Name in Windows95 with Delphi 2.0
How to Draw Template Thumbnails
List of opened applications and files
Screen Resolution
Registry and TStrings
Get Windows directory


Detecting Win95 Vs W3.X

Question


Does anyone know a quick way of detecting whether or not an application si

running on win 95 or Win3.x?

Answer


A:

I don't have Win 95 so I can't say what it will return, but the Windows API

function GetVersion returns the Windows (and DOS) version number (it's in

Delphi help). I'm running Windows for Workgroups under DOS 6.22, and this is

what I get back (Windows 3.1 gives me the same thing, I don't know how to

distinguish between 3.1 and 3.11):



var

   x: longint;

begin

   x := GetVersion;

   integer(x shr 24) --> gives me 6, the DOS major version

   integer((x shr 16) and $ff) --> gives me 22, the DOS minor version

   integer((x shr 8) and $ff)  --> gives me 10, the Windows minor version

   integer(x and $ff) --> gives me 3, the Windows major version



A:

Here's a unit I whipped together the other day in an attempt to do this. It

just checks the WINVER.EXE file for the version of the product it is shipped

with. If there's an "official" way to detect Win 3.x/95, I'd like to know.



unit Testvsn;



interface



uses

  SysUtils, WinTypes, WinProcs, VER;



procedure DoIt;



implementation



procedure DoIt;

var

  VIHandle : LongInt;

  VSize : LongInt;

  VData : Pointer;

  VVers : Pointer;

  Len : Word;

  OutStr : String;



begin

  VSize := GetFileVersionInfoSize('WINVER.EXE', VIHandle);

  If VIHandle = 0

    Then OutStr := 'Windows Version : Unknown L1'

    Else

      Begin

        GetMem(VData, VSize);

        Try

          If not GetFileVersionInfo('WINVER.EXE', VIHandle, VSize, VData)

            Then OutStr := 'Windows Version : Unknown L2'

            Else

              If not VerQueryValue(VData,'\',VVers,Len)

                Then OutStr := 'Windows Version : Unknown L3'

                Else

                  With TVS_FIXEDFILEINFO(VVers^) do

                    OutStr := 'Windows Version : ' +

                      IntToStr((dwProductVersionMS and $FFFF0000) shr 16) +

                      '.' +

                      IntToStr(dwProductVersionMS and $0000FFFF);

        Finally

          FreeMem(VData, VSize);

        End;

      End;

    OutStr := OutStr + chr(0);

    MessageBox(0,@OutStr[1],'Windows Version Test',MB_OK or MB_ICONINFORMATION);

end;



begin

  DoIt;

end.



A:

Uses the GetVersion API to determin the version of windows.



TYPE ver = RECORD

             wmaj : byte;

             wmin : byte;

             dmin : byte;

             dmaj : byte;

           END;

VAR Version : ver;



BEGIN

  Version:=getversion;

  {for windows 95 Version.wmaj = 3

                         Version.wmin = 95;}




Getting large text from TClipboard

Question


How get a large text from TClipboard?

Answer


A:

var

  Buffer: PChar;

  MyHandle : THandle;

 TextLength : Integer;

begin

MyHandle := Clipboard.GetAsHandle(CF_TEXT);

Buffer := GlobalLock(MyHandle);

If Buffer = Nil then

 begin

  GlobalUnlock(MyHandle);

  exit;

 end;



TextLength := StrLen(buffer);  {since buffer is of type PChar,

   all the functions applicable to PChar can be applied}


Long file names from Win95 DirListbox

Question


How do I get the long path string from a TDirectoryListbox in Win95 instead

of the 'hybrid' string that includes a tilde (~) character and a number?

Answer


A:

Delphi 16 in principle doesn't deal with longfilenames. But you can do it

yourself.

If you are familiar with assembly language get the M$ book "Programmer's

Guide to Microsoft Windows 95". Look in page 520 for the new DOS function

Find First File (with long filenames). It returns a  WIN32_Find_Data record with

the long and short filenames.

From what I see you can pass either one and you get back both. You have to

code it as a simple

assembler routine into your code.



It's too much to give you an example here, but if you get the book you should be

on your way. Please keep in mind that you send and receive ASCIIZ strings,

not pascal strings.


Application.Title font color

Question


Is there a way to change the color of the application's title font?

Answer


A:

You can change all windows title font colors, but not your windows title font

color. This is a windows limitation.



It is possible to create a hot spot caption and add a label to it.

If you would like to create a custom captionless and borderless form that is

movable and resizable at runtime.


Application to tile on windows desktop

Question


How can I get my Application to tile with the other windows app's currently on

the Windows Desktop? (ie using the Tile button of Task Manager).  Delphi apps

don't behave the way they should).

Answer


A:

type

  TForm1 = class(TForm)

{ ..... }

     procedure AppOnMessage(var Msg: TMsg; var Handled: Boolean);

     procedure FormCreate(Sender: TObject);

  private

	 { Private declarations }

  public

	 { Public declarations }

  end;



var

  Form1: TForm1;



implementation



procedure TForm1.FormCreate(Sender: TObject);

begin

	Application.OnMessage := AppOnMessage;

	ShowWindow(Handle, CmdShow);

end;



procedure TForm1.AppOnMessage(var Msg: TMsg; var Handled: Boolean);

var

     WindowPosp	: ^TWindowPos;

begin

     with Msg do

          if Message = WM_WINDOWPOSCHANGED then begin

		WindowPosP := pointer(lparam);

		with WindowPosP^ do begin

                    left := X;

                    Top := Y;

                    width := cx;

                    Height := cy;

                    end;

		end;

     end; { AppOnMessage }

end.



I tried it with Tile and Cascade in my Window 95 setup and it works great.



By the way the ShowWindow call that you mention is not to fix a bug. Delphi,

like Visual Basic has an invisible application form, distinct from the

main form.


Change wallpaper bitmap

Question


I want to change wallpaper (win95 desktop) bitmaps run-time.

How can i do it?

Answer


A:

The same way as in Win31 - using the SystemParametersInfo API call.



SystemParametersInfo(SPI_SETDESKWALLPAPER,0,pBitMap,SPIF_UPDATEINIFILE +

                        SPIF_SENDWININICHANGE);



This I do in one of my apps, and the app has quite successfully run

under Win31 and Win95


Obtaining Windows Version

Question


Does anyone have any code handy for determining the version

of Windows?   I'm pretty sure it's got something to do with

the GetVersion API,  but I can't seem to figure out the

bitwise operations in Delphi to determine it in a LongInt!

Answer


A:

Here's a short program that demonstrates GetVersion.



 program Winvrsn;



 uses

   WinTypes,

   WinProcs,

   SysUtils;



 var

   WinVersion : Word;

   DosVersion : Word;

   VersionString : String;



 begin

   WinVersion := GetVersion and $0000FFFF;

   DosVersion := (GetVersion and $FFFF0000) shr 16;

   VersionString := 'DOS : ' + IntToStr(Hi(DOSVersion)) + '.' + IntToStr(Lo(DOSVersion)) + #13 +

                    'Windows : '+ IntToStr(Lo(WinVersion)) + '.' + IntToStr(Hi(WinVersion)) + #0;

   MessageBox(0, @VersionString[1],'Version Information', MB_ICONINFORMATION or MB_OK)

 end.



A:

I don't know for certain what result to expect since WfW is not on my machine

anymore, but how about giving this snippet a try and let me know what

happens? It "cheats" by getting the version info from WINVER.EXE. For

Windows 95 it reads "4.00", for Windows 3.1 it says "3.10".



var

  VIHandle : LongInt;

  VSize : LongInt;

  VData : Pointer;

  VVers : Pointer;

  Len : Word;

  OutStr : String;



begin

  VSize := GetFileVersionInfoSize('WINVER.EXE', VIHandle);

  If VIHandle = 0

    Then OutStr := 'Windows Version : Unknown L1'

    Else

      Begin

        GetMem(VData, VSize);

        Try

          If not GetFileVersionInfo('WINVER.EXE', VIHandle, VSize, VData)

            Then OutStr := 'Windows Version : Unknown L2'

            Else

              If not VerQueryValue(VData,'\',VVers,Len)

                Then OutStr := 'Windows Version : Unknown L3'

                Else

                  With TVS_FIXEDFILEINFO(VVers^) do

                    OutStr := 'Windows Version : ' +

                      IntToStr((dwProductVersionMS and $FFFF0000) shr 16) +

                      '.' +

                      IntToStr(dwProductVersionMS and $0000FFFF) + #0;

        Finally

          FreeMem(VData, VSize);

        End;

      End;

    MessageBox(0,@OutStr[1],'Windows Version Test',MB_OK or MB_ICONINFORMATION);

end;


Creating and selecting palettes

Question


How do you create and use a Palette in Delphi. According to the help fn I

think you should use the CreatePalette and SetPaletteEntries and RealizePalette

but how?

Answer


A:

Below are functions that help to create a palette (an identity

palette, BTW) from an array of RGBQuads (such as you would find in 

the palette section of a .BMP file). I stole this from the WinG 

documentation, and converted it to Delphi. First call 

ClearSystemPalette, then you can get an identity palette by calling 

CreateIdentityPalette.



 If you plan to try palette animation, work in a 256-color mode, and 

change all the PC_NOCOLLAPSE entries below to PC_RESERVED.



Besides creating the palette, the other pieces to the puzzle are 



1. Override the form's GetPalette method, so that it returns the 

new palette.



2. Select and realize the new palette just before you paint.



  OldPal := SelectPalette(Canvas.Handle, NewPalette, False);

  RealizePalette(Canvas.Handle);  

  { Do your painting here }

  SelectPalette(Canvas.Handle, OldPal, False);



3. Remember to release the palette when you are done using 

DeleteObject



4. If you are used to using the RGB function to get color values, use 

the PaletteRGB function in its place.



function CreateIdentityPalette(const aRGB; nColors : Integer) : HPALETTE;

type

  QA = Array[0..255] of TRGBQUAD;

var

  Palette : PLOGPALETTE;

  PalSize : Word;

  ScreenDC : HDC;

  I : Integer;

  nStaticColors : Integer;

  nUsableColors : Integer;

begin

  PalSize := SizeOf(TLOGPALETTE) + SizeOf(TPALETTEENTRY) * 256;

  GetMem(Palette, PalSize);

  try

    with Palette^ do

      begin

        palVersion := $0300;

        palNumEntries := 256;

        ScreenDC := GetDC(0);

        try

          { For SYSPAL_NOSTATIC, just copy the color table into a PALETTEENTRY

            array and replace the first and last entries with black and white }

          if (GetSystemPaletteUse(ScreenDC) = SYSPAL_NOSTATIC)

            then

              begin

	        { Fill in the palette with the given values, marking each

                  with PalFlag }

                {$R-}

                for i := 0 to (nColors-1) do

                with palPalEntry[i], QA(aRGB)[I] do

                  begin

                    peRed := rgbRed;

                    peGreen := rgbGreen;

                    peBlue := rgbBlue;

                    peFlags := PC_NOCOLLAPSE;

                  end;



                { Mark any unused entries with PalFlag }

                for i := nColors to 255 do

                  palPalEntry[i].peFlags := PC_NOCOLLAPSE;



                { Make sure the last entry is white --

                  This may replace an entry in the array!}

                I := 255;

                with palPalEntry[i] do

                  begin

                    peRed := 255;

                    peGreen := 255;

                    peBlue := 255;

                    peFlags := 0;

                  end;



                { And the first is black --

                  This may replace an entry in the array!}

                with palPalEntry[0] do

                  begin

                    peRed := 0;

                    peGreen := 0;

                    peBlue := 0;

                    peFlags := 0;

                  end;

                {$R+}

              end

            else

              begin

	        { For SYSPAL_STATIC, get the twenty static colors into the

                  array, then fill in the empty spaces with the given color

                  table }



                { Get the static colors from the system palette }

                nStaticColors := GetDeviceCaps(ScreenDC, NUMRESERVED);

                GetSystemPaletteEntries(ScreenDC, 0, 256, palPalEntry);



                {$R-}

                { Set the peFlags of the lower static colors to zero }

                nStaticColors := nStaticColors shr 1;

                for i:= 0 to (nStaticColors-1) do

                  palPalEntry[i].peFlags := 0;



                { Fill in the entries from the given color table}

                nUsableColors := nColors - nStaticColors;

                for I := nStaticColors to (nUsableColors-1) do

                  with palPalEntry[i], QA(aRGB)[i] do

                    begin

                      peRed := rgbRed;

                      peGreen := rgbGreen;

                      peBlue := rgbBlue;

                      peFlags := PC_NOCOLLAPSE;

                    end;



                { Mark any empty entries as PC_NOCOLLAPSE }

                for i := nUsableColors to (255-nStaticColors) do

                  palPalEntry[i].peFlags := PC_NOCOLLAPSE;



                { Set the peFlags of the upper static colors to zero }

                for i := (256 - nStaticColors) to 255 do

                  palPalEntry[i].peFlags := 0;

              end;

        finally

          ReleaseDC(0, ScreenDC);

        end;

      end;

    { Return the palette }

    Result := CreatePalette(Palette^);

  finally

    FreeMem(Palette, PalSize);

  end;

end;





procedure ClearSystemPalette;

var

  Palette : PLOGPALETTE;

  PalSize : Word;

  ScreenDC : HDC;

  I : Word;

const

  ScreenPal : HPALETTE = 0;

begin

  PalSize := SizeOf(TLOGPALETTE) + SizeOf(TPALETTEENTRY) * 255; {256th = [0] }

  GetMem(Palette, PalSize);

  try

    FillChar(Palette^, PalSize, 0);

    Palette^.palVersion := $0300;

    Palette^.palNumEntries := 256;

{$R-}

    For I := 0 to 255 do

      With Palette^.palPalEntry[I] do

        peFlags := PC_NOCOLLAPSE;

{$R+}

    { Create, select, realize, deselect, and delete the palette }

    ScreenDC := GetDC(0);

    try

      ScreenPal := CreatePalette(Palette^);

      if ScreenPal <> 0

        then

          begin

            ScreenPal := SelectPalette(ScreenDC,ScreenPal,FALSE);

            RealizePalette(ScreenDC);

            ScreenPal := SelectPalette(ScreenDC,ScreenPal,FALSE);

            DeleteObject(ScreenPal);

          end;

    finally

      ReleaseDC(0, ScreenDC);

    end;

  finally

    FreeMem(Palette, PalSize);

  end;

end;


Loading a listbox with program groups

Question


So my question is,  how can I load a list box with all existing

program groups on a system?

Answer


A:

I am not sure if this approach will be helpful if the application

that ran before yours added any  groups.  i.e. whether groups get 

written to disk immediately, or only on exit from Windows....  You 

can try it out... if it works, great.... if not, and if you would 

like some programmatic control, here is some code that I pulled out 

of one of my programs...



------code---------

Procedure TProgMan.ReadGroups;

Var

  GroupData : PChar;

  TmpStr : String;

  i : integer;

begin

 GroupData := FDDEClient.RequestData('Groups');

 FGroupsList.Clear;

 FNumGroups := 0;  {assume there are no groups! }

 if GroupData = nil then

   exit

 else

   begin

     i := 0;

     TmpStr := '';

     While GroupData[i] <> #0 do

       begin

         if GroupData[i] = #13 then

           begin

             FGroupsList.Add(TmpStr);

             TmpStr := '';

             i := i + 1;  {skip the #10 char}

           end

         else

           TmpStr := TmpStr + GroupData[i];

           i := i + 1;

       end;

   end;

 StrDispose(GroupData);

end;

------------code ends-----------------



Here, FGroupsList is of type TStringlist.... therefore, you may

substitute it with Listbox.Items as easily.



A:

....

var

  Groups: PChar;

begin

   if not DDEClient.SetLink('ProgMan','PROGMAN') then

      MessageDlg('Link with ProgMan NOT established.', mtInformation, [mbOK], 0);



      DDEClient.OpenLink;



      Groups:=DDEClient.RequestData('GROUPS');



      ComboBox1.Items.SetText(Groups);



      strDispose(groups);

      DDEClient.CloseLink;





end;

.....



this code will get existing progMan groups names. and put it into a comboBox ( to let the

user select...)

Note, you don't have to allocate memory for the Groups variable, the API function

RequestData is doing this. but you have to dispose of it when through.



Of course you have to put a DDEClient component on your form.


System colors

Question


I need to emulate the color selection options of control panel... I looked

up the setsyscolor procedure, but though it seems to cause a global repaint,

it seems to have no effect... is it no longer supported? should I instead

change the win.ini (or is it system.ini - sorry - can't remember right now.)

If I change these values will programs update - or do they have to be

notified in some way?

Answer


A:

procedure TMainForm.Button4Click(Sender: TObject);

var

nColorIndex: array [1..2] of integer;

nColorValue: array [1..2] of longint;

begin

    nColorIndex[1]:=COLOR_ACTIVECAPTION;

    nColorIndex[2]:=COLOR_BTNFACE;

    nColorValue[1]:=clBlue;

    nColorValue[2]:=clRed;

    SetSysColors(2,nColorIndex,nColorValue);

    PostMessage(HWND_BROADCAST,WM_SYSCOLORCHANGE,0,0);

end;


Under Win95?

Question


How do I know if I am under Windows95?

Answer


A:

Try the windows function "getversion". Here is an example:



     versNr := LoWord(GetVersion);           {Windows-Versionsnr}

     str(lobyte(versNr),Version);

     str(hibyte(versNr), Dummy);

     if (version = '3') and (dummy = '10') then

       version := '3.10/3.11'

     else

    	 version := version + '.' +Dummy;



If Win95 is installed dummy returns 95. Version returns 3.





A:

Use the getVersion API call as follows:



   vers: longint;



   vers := GetVersion;



   {if you're certain you're running Windows 3.xx or 95, then use this:}

   if ((vers shr 8) and $ff) = 95 then

       Win 95

   else

       Win 3.xx;



   {if you could be running Windows 2.xx or 1.xx, then use this first:}

   if ((vers and $ff) = 3) then

       Win 3.xx or Win 95

   else

       Win 2.xx or Win 1.xx;



You might want to use ">=" instead of "=" to cover Win 96, etc.


Knowing that Windows is exiting

Question


I have been looking for a way to know how to differentiate between my app

closing on the users request and when Windows is closing my app because of

Windows shutting down.

Is there an easy way out, or do I have to write an event handler for the

TApplication object to look at the messages from Windows ?

Answer


A:

Windows sends a message (WM_QUERYENDSESSION) to every active

application when the user tries to shut down Windows.  If your 

program responds with a non-zero value, then Windows will close it.  

If you program returns a 0, that tells Windows not to shut down.  The 

DefWindowProc returns a non-zero value for you.  You can write a 

message handler for this message for this message that will keep 

Windows from shutting down if your program is active.


Screen Saver Register

Question


How do I register my Screen saver so Windows picks it up in the control

panel Desktop Dialog. The Application Name begins with SCRNSAVE and it

still does not register.

Answer


A:

a) In the project file (*.dpr) add '{$D SCRNSAVE } after the

uses clause.



b) On the main form, turn off the border and icon controls. In the 

activate method set the form left and top to 0, and set the Windowstate 

to wsMaximize.



c) In the form create method, set the application.OnMessage to a method 

that controls the deactivation of the screen saver. Set the 

application.OnIdle method to whatever display method for the saver.



d) In the form create method the command line should be tested for /c and 

/s. These are the command line parameters windows uses to define whether 

the screensaver should run or configure. (/c is for configuration)



e) Compile the program, and rename the .exe to .scr. Move it to the 

windows directory, and it should show up in the control panel.


Hiding apps from taskbar

Question


Anyone can tell me how to remove an Application Icon & Title from the taskbar?

Answer


ShowWindow(Application.Handle, SW_HIDE);


Reading from Registry

Question


I have some problems with reading from registry.

Does any one have a clue about solving this problem?

I get Acces Violation with the following code:



 Var

    Registry: TRegistry;

    Listan:TStrings;

 begin

      Listan.create;

      Registry := TRegistry.Create;

      try

         Registry.RootKey := HKey_Classes_Root;

         Registry.GetKeynames(Listan);

         ComboBox1.Items.AddStrings(Listan);

      finally

          Registry.Free;

      end;

 end;

Answer


Try the following. Important is the OPENKEY!



procedure TForm1.FormCreate(Sender: TObject);

Var

   Registry: TRegistry;

   Listan:TStringList;                                  // **************

begin

     Listan := TStringList.create;                      // **************

     Registry := TRegistry.Create;

     try

        Registry.RootKey := HKey_Classes_Root;

        Registry.OpenKey('',False);                     // **************

        Registry.GetKeynames(Listan);

        ComboBox1.Items := Listan;                      // **************

     finally

         Registry.Free;

     end;

end;


User Name in Windows95 with Delphi 2.0

Question


I am trying to get the username of the active user in a Windows 95, using

Delphi 2.0.

Answer


function GetUserName : string;

var

	sNetUserName	: DbiUserName;

begin



	{ Get the user name. }

	if DbiGetNetUserName(sNetUserName) = DBIERR_NONE then

		Result := StrPas(sNetUserName)

	else

		Result := '';



end;


How to Draw Template Thumbnails

Question


I'm trying to find out how to draw a thumbnail representation of a

word processing template (for example, a WordPerfect .WPT or a

Microsoft Word .DOT) on a form.  When I select an item from a

listbox, I want a thumnail of the corresponding file to be displayed on the

form.

Answer


If you mean associated icon, then you can use this:

IconIndex := 0;

Image1.Picture.Icon.Handle := ExtractAssociatedIcon( hInstance, PChar(

'c:\FileName.doc' ), IconIndex );


List of opened applications and files

Question


How to get a list of registered files and their extensions?

Answer


To get a list of the applications and their extensions for opening up

files in Windows95 do the following:



1. Open new application

2. Put a Memo component on the form, about 3 inches wide or so

3. Clear out the memo1 lines



4. Add a FormShow event and put in the following code:



procedure TForm1.FormShow(Sender: TObject);

var K: TRegIniFile;

    i: Integer;

    Extensions: TStringList;

begin

  K := TRegIniFile.Create('');

  K.RootKey := HKEY_LOCAL_MACHINE;

  K.OpenKey('SOFTWARE\MicroSoft\Windows\CurrentVersion\Extensions',

            False);



  Extensions := TStringList.Create;

  K.GetValueNames(Extensions);



  for i := 0 to Extensions.Count-1 do

    Memo1.Lines.Add(Extensions.Strings[i]

                    + ' = ' +

                    K.ReadString('', Extensions.Strings[i], ''));



  Extensions.Free;

  K.Free;

end;


Screen Resolution

Question


When I run a program on my computer everything looks fine, but when I

run it on my other computer, with a higher screen resilotion it looks

totaly different. How can I get it to look the same in any resolution.

Answer


Borland's document ti2861 gave some mileage..and I give it to you with

some of my modifications..here is:



TI2861 - Form display with different screen resolutions.



     Product: Delphi

     Version: All

     Platform: Windows/Win32 



When designing forms, it is sometimes helpful to write the code 

so that the screen and all of its objects are displayed at the 

same size no matter what the screen resolution is.  Here is 

some code to show how that is done:



implementation

const

  ScreenWidth: LongInt = 640; {I designed my form in 640x480 mode.}

  ScreenHeight: LongInt = 480;



{$R *.DFM}



procedure TForm1.FormCreate(Sender: TObject);

begin

  scaled := true;

  if (screen.width <> ScreenWidth) then

  begin

    height := longint(height) * longint(screen.height) div ScreenHeight;

    width := longint(width) * longint(screen.width) div ScreenWidth;

    scaleBy(screen.width, ScreenWidth);

  end;

end;



Then, you will want to have something that checks to see that 

the font sizes are OK.  You can iterate over each child

control's font to adjust its size as necessary.  This can be

done as follows:



type

  TFooClass = class(TControl); { needed to get at protected }

                               { font property } 



var

  i,NewFormWidth,OldFormWidth : integer;

begin

	NewFormWidth := GetsystemMetrics(0); <-- gives you your window's width

	OldFormWidth := 640;                 <-- This is my resolution

  for i := ControlCount - 1 downto 0 do

    TFooClass(Controls[i]).Font.Size := 

        (NewFormWidth div OldFormWidth) * 

        TFooClass(Controls[i]).Font.Size;

end;



This will calculate all your fonts, objects that are on your forms...



Note:  The following are issue to bear in mind when scaling 

Delphi applications (forms) on different screen resolutions:



  * Decide early on in the form design stage whether you're 

going to allow the form to be scaled or not.  The advantage of 

not scaling is that nothing changes at runtime.  The 

disadvantage of not scaling is that nothing changes at runtime 

(your form may be far too small or too large to read on some 

systems if it is not scaled).





  * If you're NOT going to scale the form, set Scaled to False.



  * Otherwise, set the Form's Scaled property to True.



  * Set AutoScroll to False.  AutoScroll = True means 'don't 

change the form's frame size at runtime' which doesn't look 

good when the  form's contents do change size.



  * Set the form's font to a scaleable TrueType font, like 

Arial.   MS San Serif is an ok alternate, but remember that it 

is still a  bitmapped font.  Only Arial will give you a font 

within a pixel of the desired height.  NOTE: If the font used 

in an application is not installed on the target computer, then 

Windows will select an  alternative font within the same font 

family to use instead.  This font may not match the same size 

of the original font any may cause problems.



  * Set the form's Position property to something other than 

poDesigned.  poDesigned leaves the form where you left it at 

design time, which for me always winds up way off to the left

on my 1280x1024 screen -  and completely off the 640x480 screen.



  * Don't crowd controls on the form - leave at least 4 pixels 

between  controls, so that a one pixel change in border 

locations (due to  scaling) won't show up as ugly overlapping 

controls.



  * For single line labels that are alLeft or alRight aligned, 

set AutoSize to True.  Otherwise, set AutoSize to False.



  * Make sure there is enough blank space in a label component 

to allow for font width changes - a blank space that is 25% of 

the length of the current string display length is a little too 

much, but safe. (You'll need at least 30% expansion space for 

string labels if you  plan to translate your app into other 

languages) If AutoSize is  False, make sure you actually set 

the label width appropriately.  If AutoSize is True, make sure 

there is enough room for the label  to grow on its own.



  * In multi-line, word-wrapped labels, leave at least one line

of blank space at the bottom.  You'll need this to catch the 

overflow when the text wraps differently when the font width 

changes with scaling. Don't assume that because you're using 

large fonts, you don't have to allow for text overflow - 

somebody else's large  fonts may be larger than yours!



  * Be careful about opening a project in the IDE at different 

resolutions.  The form's PixelsPerInch property will be 

modified as soon as the form is opened, and will be saved to 

the DFM if you save the project. It's best to test the app by 

running it standalone, and edit the form at only one 

resolution. Editing at varying resolutions and font sizes 

invites component drift  and sizing problems.



  * Speaking of component drift, don't rescale a form multiple 

times, at design time or a runtime.  Each rescaling introduces 

roundoff errors which accumulate very quickly since coordinates 

are  strictly integral.  As fractional amounts are truncated 

off control's origins and sizes with each successive 

rescaling,  the controls will appear to creep northwest and get

smaller. If you want to allow your users to rescale the form 

any number  of times, start with a freshly loaded/created form 

before each  scaling, so that scaling errors do not accumulate.



  * Don't change the PixelsPerInch property of the form, period.



  * In general, it is not necessary to design forms at any 

particular resolution, but it is crucial that you review their 

appearance at 640x480 with small fonts and large, and at a 

high-resolution with small fonts and large before releasing 

your app.  This should be  part of your regular system 

compatibility testing checklist.



  * Pay close attention to any components that are essentially  

single-line TMemos - things like TDBLookupCombo.  The Windows  

multi-line edit control always shows only whole lines of text 

-  if the control is too short for its font, a TMemo will show  

nothing at all (a TEdit will show clipped text). For such  

components, it's better to make them a few pixels too large 

than to be one pixel too small and show not text at all.



  * Keep in mind that all scaling is proportional to the 

difference  in the font height between runtime and design time, 

NOT the pixel resolution or screen size.  Remember also that 

the origins of your controls will be changed when the form is 

scaled - you can't very  well make components bigger without 

also moving them over a bit.


Registry and TStrings

Question


I want to save the contents of a string list to the registry (and later read

it back).  It looks like the ReadSectionValues method of TRegIniFile may

read back the list.

Answer


If anyone is interested, the code that I used to write (and read) a

TStringList to the Registry is:



{Save a list of strings to the registry.

 It will write each string as a key,value with the key being the index of

 each string element and the value being the key.

}

procedure TDPRegistry.SaveStringListInRegistry(_RootKey: HKEY;

                                     _Localkey: String; Strings: TStrings);

var

  TR: TRegIniFile;

  LStringIndex: Integer;

begin

  TR := TRegIniFile.Create('');

  try

    case _RootKey of { default is RootKey=HKEY_CURRENT_USER }

      HKEY_CLASSES_ROOT,

      HKEY_CURRENT_USER,

      HKEY_LOCAL_MACHINE,

      HKEY_USERS,

      HKEY_PERFORMANCE_DATA,

      HKEY_CURRENT_CONFIG,

      HKEY_DYN_DATA : TR.RootKey := _RootKey;

    end; {end case _RootKey}

    TR.EraseSection(_Localkey); {make sure no entries for this section/key}

    with TRegistry(TR) do begin

      if OpenKey(_Localkey,true) then begin

        try

          for LStringIndex := 0 to Strings.Count - 1 do begin

            WriteString (IntToStr(LStringIndex), Strings[LStringIndex]);

          end; {for each string in the list}

        finally

          CloseKey;

        end; {try finally}

      end; {if OpenKey}

    end; {with TRegistry(TR)}

  finally

    TR.Free;

  end; {try finally}

end;



{Get list of strings from registry.}

procedure TDPRegistry.GetStringListFromRegistry(_RootKey: HKEY;

                                     _Localkey: String; Strings: TStrings);

var

  TR: TRegIniFile;

  LStringIndex: Integer;

  RegKeyInfo : TRegKeyInfo;

begin

  Strings.Clear; {start with no elements in string list}

  TR := TRegIniFile.Create('');

  try

    case _RootKey of { default is  RootKey=HKEY_CURRENT_USER  }

      HKEY_CLASSES_ROOT,

      HKEY_CURRENT_USER,

      HKEY_LOCAL_MACHINE,

      HKEY_USERS,

      HKEY_PERFORMANCE_DATA,

      HKEY_CURRENT_CONFIG,

      HKEY_DYN_DATA : TR.RootKey := _RootKey;

    end;

{   TR.ReadSectionValues(_Localkey, Strings); doesn't work nicely because

returns strings as "1=Value", "2=Value"...}

    with TRegistry(TR) do begin

      if OpenKey(_Localkey,true) then begin

        try

          if (GetKeyInfo(RegKeyInfo)) then begin

            for LStringIndex := 0 to RegKeyInfo.NumValues - 1 do begin

              Strings.Add(ReadString(IntToStr(LStringIndex)));

            end; {for each value associated with this key}

          end; {got key information}

        finally

          CloseKey;

        end; {try finally}

      end; {if OpenKey}

    end; {with TRegistry(TR)}

  finally

    TR.Free;

  end; {try finally}

end;


Get Windows directory

Question


How to retrieve Windows directory?

Answer


{this code finds the windows directory on the click of a button}



procedure TForm1.Button1Click(Sender: TObject);

var

   buf : array[0..200] of char;

   pc : Pchar;

   str : string;

   x : integer;

begin

   pc := @buf[0];

   x := getwindowsdirectory(pc, 199);

   str := strpas(pc);

   writeln(str); { output c:\windows}

   writeln(x);   { output 10}

end;




Close    To Top
  • Prev Article-Programming:
  • Next Article-Programming:
  • Now: Tutorial for Web and Software Design > Programming > delphi > Programming Content
    Photoshop Tutorial
     

    Special Effect

      3D Effect
      Photoshop Articles
    Programming Tutorial
     

    C/C++ Tutorial

      Visual Basic
      C# Tutorial
    Database Tutorial
     

    MySQL Tutorial

      MS SQL Tutorial
      Oracle Tutorial
    Geek Tutorial
     

    Blogging Tutorial

      RSS Tutorial
      Podcasting Tutorial
    Graphic Design Tutorial
      Coreldraw Tutorial
      Illustrator Tutorial
      3D Tutorials
    Webmaster Articles
     

    Domain Service

      Web Hosting
      Site Promotion
    Java Tutorial/ Articles
     

    Java Servlets

      JavaEE Tutorial
     

    JavaBeans Tutorial

    XML Tutorial/ Articles
     

    XML Style

      AJAX Tutorial
      XML Mobile
    Flash Tutorial/ Articles
     

    Flash Video

      Action Script
      Flash Articles
    OS Tutorial/ Articles
      Linux Tutorial
      Symbian Tutorial
      MacOS Tutorial
    Personal Tech
      Hardware Tutorial
      Software Tutorial
      Online Auction