home *** CD-ROM | disk | FTP | other *** search
- Unit GrpFile;
- {This unit provides various functions to read data from the Windows
- group files}
- Interface
-
- Uses WinTypes;
-
- Type IconEnum = Procedure(Icon:hIcon);
-
- Function GetIcon(Group:PChar; Index:Integer):hIcon;
- Procedure EnumIcons(Group:PChar; EnumProc:IconEnum);
- Function GetGroupName(Description:PChar; GroupName:PChar; Len:Word):PChar;
- Function GetGroupDDE(Group:PChar):PChar;
-
- Implementation
-
- Uses WinProcs, Strings;
-
- Type tagGroupHeader = Record {Group file fixed length header}
- identifier:Array [0..3] of Char; {always 'PMCC'}
- wCheckSum:Word; {file checksum}
- cbGroup:Word; {size of Windows 3.0 compatible
- portion of file. In Win 3.1 it is the offset to the tagdata.}
- nCmdShow:Word; {Normal, minimized, maximized}
- rcNormal:TRect; {Rectangle for show normal}
- ptMin:TPoint; {Point for show minimized}
- pName:Word; {Offset of description}
- wLogPixelsX:Word; {Width of icon}
- wLogPixelsY:Word; {Height of icon}
- Case Boolean of
- False: (wBitsperPixel:Word; {Windows 3.0}
- wPlanes:Word; {Windows 3.0}
- cItems:Word); {Windows 3.0 & 3.1} {Number of items
- in the griItems array}
- True: (bBitsperPixel:Byte; {Windows 3.1}
- bPlanes:Byte; {Windows 3.1}
- cItems31:Word; {Windows 3.0 & 3.1 duplicates cItems}
- Reserved:Word);
- {rgiItems:Array [0..cItems-1] of Word;} {array of offsets to tagItemInfo items}
- End;
-
- Type tagItemInfo = Record {Data for an individual program}
- pt:TPoint; {Point for program icon}
- iIcon:Word; {Index of icon in icon file}
- cbHeader:Word; {Size of tagCURSORSHAPE}
- cbANDPlane:Word; {Size of AND bits for icon}
- cbXORPlane:Word; {Size of XOR bits for icon}
- pHeader:Word; {Offset of a tagCURSORSHAPE}
- pANDPlane:Word; {Offset of AND bits for icon}
- pXORPlane:Word; {Offset of XOR bits for icon}
- pName:Word; {Offset of description of program}
- pCommand:Word; {Offset of command line for program}
- pIconPath:Word; {Offset of icon file name}
- End;
-
- Type tagCURSORSHAPE = Record {Info about icon for a program}
- xHotSpot:Integer; {Always 0}
- yHotSpot:Integer; {Always 0}
- cx:Integer; {width of program icon}
- cy:Integer; {height of program icon}
- cbWidth:Integer; {Bytes of data per row
- accounting for WORD alignment.}
- bPlanes:Byte; {Number of display planes for icon}
- bBitsPixel:Byte; {Bits per pixel for icon}
- End;
-
- Type tagTAGDATA = Record {Windows 3.1 auxillary info}
- wID:Word; { $8101 for path, $8102 for hotkey, $8103 for minimized}
- { $8000 for first tagdata; path element of 'PMCC'}
- { $FFFF for last tagdata}
- wItem:Word; {Program index that tag refers to}
- cb:Word; {Size of TAGDATA data structure}
- Case Boolean of
- False: (Path:Array [0..255] of Char); {Path}
- True: (HotKey:Word); {Program hotkey}
- End;
-
- Type WArray = Array [0..0] of Word;
- Type PArray = ^WArray;
-
- Var GroupHeader:tagGroupHeader;
- ItemInfo:tagItemInfo;
- CursorShape:tagCURSORSHAPE;
- TagData:tagTAGDATA;
- Grp:File;
- rgiItems:PArray;
-
- Function OpenGroup(FName:PChar):Integer;
- {Internal function. Opens a group file, loads the fixed header (GroupHeader)
- and loads the variable length header (rgiItems).
- Returns 0 if everything OK.
-
- Input: FName - Name of group file}
-
- Var OldFileMode:Byte;
- Result:Integer;
- Len,I,J:Word;
-
- Begin
- OldFileMode:=FileMode;
- FileMode:=0;
- Assign(Grp,FName);
- {$I-} Reset(Grp,1); {$I+}
- Result:=IOResult;
- OpenGroup:=Result;
- FileMode:=OldFileMode;
- If Result = 0 then
- Begin {Read the fixed header}
- BlockRead(Grp,GroupHeader,Sizeof(GroupHeader),Len);
- If (Len <> Sizeof(GroupHeader)) or
- (StrLComp(GroupHeader.identifier,'PMCC',4) <> 0)then
- {If I wanted to be really rigorous here, I could read the entire
- file as WORD items and the sum should be zero. The wCheckSum word
- is adjusted to insure this.}
- Begin
- OpenGroup:=1;
- Close(Grp);
- Exit;
- End;
- rgiItems:=Nil; {Now load the variable length header section}
- If GroupHeader.cItems = 0 then Exit;
- GetMem(rgiItems,GroupHeader.cItems*Sizeof(Word));
- BlockRead(Grp,rgiItems^,GroupHeader.cItems*Sizeof(Word),Len);
- If Len <> GroupHeader.cItems*Sizeof(Word) then
- Begin
- OpenGroup:=1;
- Close(Grp);
- FreeMem(rgiItems,GroupHeader.cItems*Sizeof(Word));
- rgiItems:=Nil;
- Exit;
- End;
- End;
- End;
-
- Procedure CloseGroup;
- {Internal procedure. Closes the group file and frees any memory allocated
- by OpenGroup.}
-
- Begin
- If rgiItems <> Nil then
- FreeMem(rgiItems,GroupHeader.cItems*Sizeof(Word));
- Close(Grp);
- End;
-
- Function ReadIcon(Index:Word):hIcon;
- {Internal function. Loads an icon from the group file.
- Returns the handle of the icon.
-
- Input: Index - the index in rgiItems of the program for which to load
- the icon}
-
- Var ANDBits,XORBits:Pointer;
- Len:Word;
-
- Begin
- ReadIcon:=0;
- If (rgiItems = Nil) or (rgiItems^[Index] = 0) then Exit;
- Seek(Grp,rgiItems^[Index]);
- BlockRead(Grp,ItemInfo,Sizeof(ItemInfo),Len);
- If Len <> Sizeof(ItemInfo) then Exit;
- Seek(Grp,ItemInfo.pHeader);
- Blockread(Grp,CursorShape,Sizeof(CursorShape),Len);
- If Len <> Sizeof(CursorShape) then Exit;
- GetMem(ANDBits,ItemInfo.cbANDPlane);
- GetMem(XORBits,ItemInfo.cbXORPlane);
- Seek(Grp,ItemInfo.pANDPlane);
- BlockRead(Grp,ANDBits^,ItemInfo.cbANDPlane,Len);
- If Len = ItemInfo.cbANDPlane then
- Begin
- Seek(Grp,ItemInfo.pXORPlane);
- BlockRead(Grp,XORBits^,ItemInfo.cbXORPlane,Len);
- If Len = ItemInfo.cbXORPlane then
- ReadIcon:=CreateIcon(hInstance,CursorShape.cx,
- CursorShape.cy,CursorShape.bPlanes,
- CursorShape.bBitsPixel,ANDBits,XORBits);
- End;
- FreeMem(XORBits,ItemInfo.cbXORPlane);
- FreeMem(ANDBits,ItemInfo.cbANDPlane);
- End;
-
- Function GetProgramPath(Index:Word):PChar;
- {Internal function. Returns a pointer to the program path if found,
- else returns a pointer to an empty string.
-
- Input: Index - The index of the program item}
-
- Var Len:Integer;
-
- Begin
- GetProgramPath:=@TagData.Path;
- Seek(Grp,GroupHeader.cbGroup);
- BlockRead(Grp,TagData,Sizeof(TagData)-Sizeof(TagData.Path),Len);
- While (Len = (Sizeof(TagData)-Sizeof(TagData.Path))) and
- (TagData.wID <> $FFFF) do
- Begin
- If TagData.cb > Sizeof(TagData)-Sizeof(TagData.Path) then
- BlockRead(Grp,TagData.Path,TagData.cb-(Sizeof(TagData)-Sizeof(TagData.Path)),Len);
- If (TagData.wID = $8101) and (TagData.wItem = Index) then
- Len:=0
- else
- BlockRead(Grp,TagData,Sizeof(TagData)-Sizeof(TagData.Path),Len);
- End;
- If (TagData.wID <> $8101) or (TagData.wItem <> Index) then
- TagData.Path[0]:=#0;
- End;
-
- Function GetProgramHotKey(Index:Word):Word;
- {Internal function. Returns the hotkey for the program if found else zero.
-
- Input: Index - The index of the program item}
-
- Var Len:Integer;
-
- Begin
- GetProgramHotKey:=0;
- Seek(Grp,GroupHeader.cbGroup);
- BlockRead(Grp,TagData,Sizeof(TagData)-Sizeof(TagData.Path),Len);
- While (Len = (Sizeof(TagData)-Sizeof(TagData.Path))) and
- (TagData.wID <> $FFFF) do
- Begin
- If TagData.cb > Sizeof(TagData)-Sizeof(TagData.Path) then
- BlockRead(Grp,TagData.Path,TagData.cb-(Sizeof(TagData)-Sizeof(TagData.Path)),Len);
- If (TagData.wID = $8102) and (TagData.wItem = Index) then
- Begin
- GetProgramHotKey:=TagData.HotKey;
- Len:=0;
- End
- else
- BlockRead(Grp,TagData,Sizeof(TagData)-Sizeof(TagData.Path),Len);
- End;
- End;
-
- Function GetProgramMinFlag(Index:Word):Boolean;
- {Internal function. Returns TRUE if the program runs minimized.
-
- Input: Index - The index of the program item}
-
- Var Len:Integer;
-
- Begin
- GetProgramMinFlag:=False;
- Seek(Grp,GroupHeader.cbGroup);
- BlockRead(Grp,TagData,Sizeof(TagData)-Sizeof(TagData.Path),Len);
- While (Len = (Sizeof(TagData)-Sizeof(TagData.Path))) and
- (TagData.wID <> $FFFF) do
- Begin
- If TagData.cb > Sizeof(TagData)-Sizeof(TagData.Path) then
- BlockRead(Grp,TagData.Path,TagData.cb-(Sizeof(TagData)-Sizeof(TagData.Path)),Len);
- If (TagData.wID = $8103) and (TagData.wItem = Index) then
- Begin
- GetProgramMinFlag:=True;
- Len:=0;
- End
- else
- BlockRead(Grp,TagData,Sizeof(TagData)-Sizeof(TagData.Path),Len);
- End;
- End;
-
- Function GetIcon(Group:pChar; Index:Integer):hIcon;
- {External function. Loads an icon from a group file.
- Returns the handle to the icon.
-
- Input: Group - The name of the group file
- Index - The index in rgiItems of the program icon}
-
- Begin
- GetIcon:=0;
- If OpenGroup(Group) <> 0 then Exit;
- If GroupHeader.cItems > Index then
- GetIcon:=ReadIcon(Index);
- CloseGroup;
- End;
-
- Procedure EnumIcons(Group:PChar; EnumProc:IconEnum);
- {External procedure. Calls a procedure for each icon in the group file.
-
- Input: Group - The name of the group file
- EnumProc - The address of the procedure to call. It must have the
- format: Procedure EnumProc(Icon:hIcon); Far; }
-
- Var I:Word;
- Icon:hIcon;
-
- Begin
- If OpenGroup(Group) <> 0 then Exit;
- If rgiItems <> Nil then
- For I:=0 to GroupHeader.cItems-1 do
- If rgiItems^[I] <> 0 then
- Begin
- Icon:=ReadIcon(I);
- If Icon <> 0 then
- Begin
- EnumProc(Icon);
- DestroyIcon(Icon);
- End;
- End;
- CloseGroup;
- End;
-
- Function GetGroupName(Description:PChar; GroupName:PChar; Len:Word):PChar;
- {External function. Takes a group description and find the corresponding
- group file. Returns a pointer to the group file name.
-
- Input: Description - The description under the group icon in the
- Program Manager
- Len - The length of the output array
-
- Output: GroupName - The output array which receives the file name}
-
- Var PG,PGroup,PDesc,FName:PChar;
- I,J,K:Word;
-
- Begin
- GroupName[0]:=#0;
- GetGroupName:=GroupName;
- I:=500;
- GetMem(PGroup,I);
- While GetPrivateProfileString('Groups',Nil,'',PGroup,I,'PROGMAN.INI') = I-1 do
- Begin
- Freemem(PGroup,I);
- Inc(I,500);
- GetMem(PGroup,I);
- End;
- J:=StrLen(Description)+1;
- GetMem(PDesc,J+1);
- GetMem(FName,256);
- PG:=PGroup;
- While (PG^ <> #0) and (GroupName^ = #0) do
- Begin
- If (GetPrivateProfileString('Groups',PG,'',FName,256,'PROGMAN.INI') > 0) and
- (OpenGroup(FName) = 0) then
- Begin
- Seek(Grp,GroupHeader.pName);
- BlockRead(Grp,PDesc^,J,K);
- PDesc[K]:=#0;
- If StrComp(PDesc,Description) = 0 then
- StrLCopy(GroupName,FName,Len);
- CloseGroup;
- End;
- Inc(PG,StrLen(PG)+1);
- End;
- FreeMem(FName,256);
- FreeMem(PDesc,J+1);
- FreeMem(PGroup,I);
- End;
-
- Function GetGroupDDE(Group:PChar):PChar;
- {External function. This function returns a pointer to a memory area which
- receives data in a format similar (but not quite identical) to the Windows
- 3.1 Program Manager DDE interface for a particular group. This function
- will work with Windows 3.0, which does not support that particular
- DDE interface. It is up to the caller to do a StrDispose on the array.
-
- Input: Group - The name of the group file}
-
- Var PDDE,PFinal:PChar;
- I,J,Len:Word;
-
- Procedure Str(I:Word; P:PChar);
- Var S:String [10];
-
- Begin
- System.Str(I,S);
- StrPCopy(P,S);
- End;
-
- Begin
- GetGroupDDE:=Nil;
- If OpenGroup(Group) <> 0 then Exit;
- GetMem(PDDE,(GroupHeader.cItems+1)*1024);
- If PDDE = Nil then
- Begin
- CloseGroup;
- Exit;
- End;
- StrCopy(PDDE,'"');
- Seek(Grp,GroupHeader.pName);
- BlockRead(Grp,StrEnd(PDDE)^,256,Len);
- StrCat(PDDE,'",');
- StrCat(PDDE,Group);
- StrCat(PDDE,',');
- PFinal:=StrEnd(PDDE);
- I:=GroupHeader.cItems;
- If I > 0 then
- For J:=0 to I-1 do
- If rgiItems^[J] = 0 then Dec(I);
- Str(I,PFinal);
- StrCat(PFinal,',');
- Str(GroupHeader.ptMin.Y,StrEnd(PFinal));
- StrCat(PFinal,^M^J);
- If GroupHeader.cItems > 0 then
- For I:=0 to GroupHeader.cItems-1 do
- If rgiItems^[I] <> 0 then
- Begin
- Seek(Grp,rgiItems^[I]);
- BlockRead(Grp,ItemInfo,Sizeof(ItemInfo),Len);
- If Len <> Sizeof(ItemInfo) then
- Begin
- FreeMem(PDDE,(GroupHeader.cItems+1)*1024);
- CloseGroup;
- Exit;
- End;
- PFinal:=StrEnd(PFinal);
- StrCat(PFinal,'"');
- Seek(Grp,ItemInfo.pName);
- BlockRead(Grp,StrEnd(PFinal)^,256,Len);
- StrCat(PFinal,'","');
- Seek(Grp,ItemInfo.PCommand);
- BlockRead(Grp,StrEnd(PFinal)^,256,Len);
- StrCat(PFinal,'",');
- StrCat(PFinal,GetProgrampath(I));
- StrCat(PFinal,',');
- Seek(Grp,ItemInfo.pIconPath);
- BlockRead(Grp,StrEnd(PFinal)^,256,Len);
- StrCat(PFinal,',');
- Str(ItemInfo.pt.x,StrEnd(PFinal));
- StrCat(PFinal,',');
- Str(ItemInfo.pt.y,StrEnd(PFinal));
- StrCat(PFinal,',');
- Str(ItemInfo.iIcon,StrEnd(PFinal));
- StrCat(PFinal,',');
- Str(GetProgramHotKey(I),StrEnd(PFinal));
- StrCat(PFinal,',');
- Str(Byte(GetProgramMinFlag(I)),StrEnd(PFinal));
- StrCat(PFinal,^M^J);
- End;
- PFinal:=StrNew(PDDE);
- FreeMem(PDDE,(GroupHeader.cItems+1)*1024);
- CloseGroup;
- GetGroupDDE:=PFinal;
- End;
-
- Begin
- End.