Get name Drive Hardware - windows

hello someone could help me how to get
the name of the drive / hardware / / 'C: \' 'D: \' .......
example
NameDrive function (const sDrive: string): string;
begin
  result: = GetDriveName (sDrive);
end;
Showmessage (NameDrive ('C: \')) / / = ST500DM0 ....
Thank you for attention.

It's possible to get vendor info by calling DeviceIoControl with IOCTL_STORAGE_QUERY_PROPERTY code (STORAGE_PROPERTY_QUERY PropertyId set to StorageDeviceProperty), or with SMART_ control codes, or by reading WMI data. in any case you should work with physical drives having names like \.\PhysicalDriveX rather than logical ones. These are 3 alternatives I can see at once.
Example of method 1 (type definitions taken from DDK):
type
STORAGE_PROPERTY_ID = (
StorageDeviceProperty,
StorageAdapterProperty,
StorageDeviceIdProperty,
StorageDeviceUniqueIdProperty, // See storduid.h for details
StorageDeviceWriteCacheProperty,
StorageMiniportProperty,
StorageAccessAlignmentProperty,
StorageDeviceSeekPenaltyProperty,
StorageDeviceTrimProperty,
StorageDeviceWriteAggregationProperty
);
STORAGE_QUERY_TYPE = (
PropertyStandardQuery, // Retrieves the descriptor
PropertyExistsQuery, // Used to test whether the descriptor is supported
PropertyMaskQuery, // Used to retrieve a mask of writeable fields in the descriptor
PropertyQueryMaxDefined // use to validate the value
);
STORAGE_PROPERTY_QUERY = packed record
PropertyId, // ID of the property being retrieved
QueryType : Cardinal; // Flags indicating the type of query being performed
AdditionalParameters : array [0..0] of AnsiChar; // Space for additional parameters if necessary
end;
STORAGE_DEVICE_DESCRIPTOR = packed record
Version,
Size : Cardinal;
DeviceType : Byte;
DeviceTypeModifier : Byte;
RemovableMedia,
CommandQueueing : Byte;
VendorIdOffset,
ProductIdOffset,
ProductRevisionOffset,
SerialNumberOffset : Cardinal;
BusType : Cardinal;
RawPropertiesLength : Cardinal;
RawDeviceProperties : array [0..0] of AnsiChar;
end;
const STORAGE_PROPERTY_QUERY_SIZE = 12;
function GetDriveModel(DrvHandle : THandle; var aModel : AnsiString; out ErrCode : Integer) : Boolean;
var PropQuery : STORAGE_PROPERTY_QUERY;
PropResponse : STORAGE_DEVICE_DESCRIPTOR;
PropResponseSize, i : Cardinal;
Buf : PByte;
begin
FillChar(PropQuery, STORAGE_PROPERTY_QUERY_SIZE, 0);
PropQuery.PropertyId := Cardinal(StorageDeviceProperty);
PropQuery.QueryType := Cardinal(PropertyStandardQuery);
Buf := GetMemory(4096);
Result := DeviceIoControl(DrvHandle, IOCTL_STORAGE_QUERY_PROPERTY, #PropQuery, STORAGE_PROPERTY_QUERY_SIZE, Buf, 4096, PropResponseSize, nil);
ErrCode := GetLastError;
if not Result then
begin
FreeMemory(buf);
Exit;
end;
PropResponse := (PSTORAGE_DEVICE_DESCRIPTOR(Buf))^;
if PropResponse.RawPropertiesLength <> 0 then
begin
aModel := '';
if PropResponse.VendorIdOffset <> 0 then
begin
i := PropResponse.VendorIdOffset;
while Buf[i] <> 0 do
begin
aModel := aModel + AnsiChar(Buf[i]);
Inc(i);
end;
end;
if PropResponse.ProductIdOffset <> 0 then
begin
aModel := aModel + ' ';
i := PropResponse.ProductIdOffset;
while Buf[i] <> 0 do
begin
aModel := aModel + AnsiChar(Buf[i]);
Inc(i);
end;
end;
end;
FreeMemory(buf);
end;
A drive should be opened this way:
Result := CreateFile(PWideChar(DrvName), GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
where DrvName is e.g. \\.\PhysicalDrive0 for 1st drive in the system.
Generally speaking, it's not possible to do what you want exactly, because a single volume, say, D:\ may be a dynamic one spanning several physical disks.

Related

Take screenshot of a FMX form from another process, even if the form is not topmost / modal

I am currently trying to take a screenshot of a 2D Firemonkey (FMX) form from another process.
The following is using a well-known method based of GDI, using a BitBlt() to produce a bitmap, and WIC to save it to a PNG file.
{...}
uses
system.UITypes,
system.SysUtils,
system.Hash,
{$IF Defined(MSWINDOWS)}
winapi.Windows,
Winapi.Direct3D9,
WinApi.D3DX9,
Winapi.Wincodec,
WinApi.ActiveX,
{$ENDIF}
{ some internal units }
path.types,
path.utils,
os.utils;
{...}
Type
TWindowSnapshot = record
window_handle: THandle; // handle to window
process_id: Cardinal; // PID of the process
window_rect: TRect; // position of the window
title: string; // title
file_path: string; // path to the window's image file
end;
TWindowSnapshots = Tarray<TWindowSnapshot>;
procedure HRCHECK(r: HRESULT); inline;
begin
if r <> S_OK then abort;
end;
function pad(s,g:integer): integer; inline;
begin
dec(g);
result := (s + g) and not g;
end;
function WICSavePixelsToPng(r: TRect; stride: cardinal; pixels: PByte; filePath: string): HRESULT;
var
factory: IWICImagingFactory;
encoder: IWICBitmapEncoder;
frame: IWICBitmapFrameEncode;
encoderOptions: IPropertyBag2;
stream: IWICStream;
pf: TGUID;
coInit : HResult;
begin
result := E_INVALIDARG;
if not assigned(pixels) then exit;
if (filepath = '') then exit;
coInit := CoInitialize(nil);
pf := GUID_WICPixelFormat32bppBGRA;
result := CoCreateInstance(CLSID_WICImagingFactory, nil, CLSCTX_INPROC_SERVER, IWICImagingFactory, factory);
if result <> S_OK then exit;
result := factory.CreateStream(&stream);
if result <> S_OK then exit;
result := stream.InitializeFromFilename(PWideChar(filePath), GENERIC_WRITE);
if result <> S_OK then exit;
result := factory.CreateEncoder(GUID_ContainerFormatPng, TGUID.Empty, encoder);
if result <> S_OK then exit;
result := encoder.Initialize(stream, WICBitmapEncoderNoCache);
if result <> S_OK then exit;
result := encoder.CreateNewFrame(frame, encoderOptions);
if result <> S_OK then exit;
result := frame.Initialize(nil);
if result <> S_OK then exit;
result := frame.SetSize(r.width, r.height);
if result <> S_OK then exit;
result := frame.SetPixelFormat(pf);
if result <> S_OK then exit;
if pf <> GUID_WICPixelFormat32bppBGRA then
begin
assert(false,'ToDo');
end;
inc(pixels,(r.Left*4) + r.Top * stride);
result := frame.WritePixels(r.height, stride, stride * r.height, pixels);
if result <> S_OK then exit;
result := frame.Commit();
if result <> S_OK then exit;
result := encoder.Commit();
if (coInit <> 0) then
CoUninitialize();
end;
function take_window_snapshot_GDI(win_handle: THandle; PID: Cardinal; out cs: TWindowSnapshot; const image_folder: string): boolean;
var
Wr: TRect;
HdcSRC: HDC;
hDCDest: HDC;
hBmp: HBITMAP;
hOld: HGDIOBJ;
hFlags: Cardinal;
l: integer;
src_shot,dst_shot,lsrc,ldst: PByte;
sr: PRGBTriple;
dr: PRGBQuad;
buff_size: cardinal;
x,y, src_stride, dst_stride: integer;
bi: tagBITMAPINFO;
begin
result := false;
cs.window_handle := win_handle;
cs.title := '';
cs.window_rect := TRect.Empty;
cs.process_id := 0;
try
hFlags := GetWindowLong(win_handle,GWL_STYLE);
if (hFlags and (WS_DLGFRAME or WS_POPUP)) = 0 then exit;
if (hFlags and WS_VISIBLE) = 0 then exit;
GetWindowRect(win_handle,Wr);
if (Wr.Width = 0) or (Wr.Height = 0) then exit;
L := GetWindowTextLength(win_handle);
if L > 0 then
begin
setlength(cs.title,L);
GetWindowText(win_handle,pchar(cs.title),L+1);
end;
{ reserve memory for bitmaps }
src_stride := pad((wr.Width * 3),4);
dst_stride := pad((wr.Width * 4),4);
buff_size := src_stride * wr.Height;
getmem(src_shot,buff_size);
if not assigned(src_shot) then exit;
getmem(dst_shot,dst_stride * wr.Height);
if not assigned(src_shot) then
begin
freemem(src_shot);
exit;
end;
try
try
HdcSRC := GetWindowDC(win_handle);
HdcDest := CreateCompatibleDC(HdcSRC);
SetStretchBltMode(HdcDest, COLORONCOLOR);
HBmp := CreateCompatibleBitmap(HdcSRC,Wr.Width,wr.Height);
hOld := SelectObject(hDCDest,hBmp);
BitBlt(hDCDest,0,0,wr.width,wr.Height,HdcSRC,0,0,SRCCOPY);
{ target bitplane is 24 bits RGB }
bi := default(tagBITMAPINFO);
bi.bmiHeader.biSize := sizeof(TBitmapInfoHeader);
bi.bmiHeader.biWidth := wr.Width;
bi.bmiHeader.biHeight := wr.Height;
bi.bmiHeader.biPlanes := 1;
bi.bmiHeader.biBitCount := 24;
bi.bmiHeader.biCompression := BI_RGB;
GetDIBits(hDCDest,HBmp,0,wr.Height,src_shot,bi,DIB_RGB_COLORS);
{ now convert pixels to RGBA, in correct line order.
On Windows, last line is first in bitmap }
ldst := dst_shot;
lsrc := src_shot + (src_stride * wr.Height);
for y := 0 to wr.Height - 1 do
begin
dec(lsrc,src_stride);
sr := pointer(lsrc);
dr := pointer(ldst);
for x := 0 to wr.Width - 1 do
begin
dr.rgbBlue := sr.rgbtBlue;
dr.rgbRed := sr.rgbtRed;
dr.rgbGreen := sr.rgbtGreen;
dr.rgbReserved := 255;
inc(dr);
inc(sr);
end;
inc(ldst,dst_stride);
end;
{ save to PNG with WIC }
var tmp_name := Tpath.GetTempFileName('png',false,image_folder);
wr.Offset(-wr.Left,-wr.top);
if WICSavePixelsToPng(wr,dst_stride,dst_shot,tmp_name) = S_OK then
begin
result := true;
{ rename temp file name to new name if it doesn't exist already }
var new_name := Tpath.ExtractDirectory(tmp_name) + THashSHA1.GetHashStringFromFile(tmp_name) + '.png';
if not TPath.FileExists(new_name) then
begin
if Tfile.Rename(tmp_name,new_name) then
begin
cs.file_path := '';
end else begin
cs.file_path := new_name;
end;
end else begin
cs.file_path := new_name;
end;
end;
Tfile.Delete(tmp_name);
result := true;
finally
freemem(src_shot);
freemem(dst_shot);
end;
finally
SelectObject(hDCDest,hold);
DeleteDC(hDCDest);
ReleaseDC(win_handle,HdcSRC);
end;
except begin
result := false;
end;
end;
end;
This method is working for Delphi forms using VCL, however with forms using Firemonkey (FMX) 2D, it only produces bitmaps filled with BLACK (0) pixels.
I have tried an alternative using Direct3D9, that is working for Firemonkey form, however with a limitation I'll explain after the code snippet
function Take_window_snapshot_D3D(win_handle: THandle; PID: Cardinal; out cs: TWindowSnapshot; const image_folder: string): boolean;
var
D3D: IDirect3D9;
D3DDevice: IDirect3DDevice9;
mode: D3DDISPLAYMODE;
device: IDirect3DDevice9;
surface: IDirect3DSurface9;
parameters: D3DPRESENT_PARAMETERS;
rc: D3DLOCKED_RECT;
pitch: UINT;
shot: PByte;
shot_size: cardinal;
adapter: cardinal;
wr: TRect;
hCurWnd: THandle;
hCurThreadID: Cardinal;
L: integer;
hFlags: cardinal;
hr: HRESULT;
begin
result := false;
cs := default(TWindowSnapshot);
try
{ get the window type }
hFlags := GetWindowLong(win_handle,GWL_STYLE);
if (hFlags and (WS_DLGFRAME or WS_POPUP)) = 0 then exit;
if (hFlags and WS_VISIBLE) = 0 then exit;
{ size }
GetWindowRect(win_handle,Wr);
if (Wr.Width = 0) or (Wr.Height = 0) then exit;
{ title }
L := GetWindowTextLength(win_handle);
if L > 0 then
begin
setlength(cs.title,L);
GetWindowText(win_handle,pchar(cs.title),L+1);
end;
cs.window_handle := win_handle;
cs.window_rect := wr;
cs.process_id := PID;
{ Direct3D capture }
adapter := D3DADAPTER_DEFAULT;
D3D := Direct3DCreate9(D3D_SDK_VERSION);
HRCHECK(D3D.GetAdapterDisplayMode(adapter,mode));
parameters := default(D3DPRESENT_PARAMETERS);
parameters.Windowed := TRUE;
parameters.BackBufferCount := 1;
parameters.BackBufferHeight := mode.Height;
parameters.BackBufferWidth := mode.Width;
parameters.SwapEffect := D3DSWAPEFFECT_DISCARD;
parameters.hDeviceWindow := win_handle;
{ create device & capture surface }
HRCHECK(d3d.CreateDevice(adapter, D3DDEVTYPE_HAL, win_handle, D3DCREATE_SOFTWARE_VERTEXPROCESSING, #parameters, device));
{ create surface }
HRCHECK(device.CreateOffscreenPlainSurface(mode.Width, mode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, nil));
{ bring our window to front }
hCurWnd := GetForegroundWindow;
hCurThreadID := GetCurrentThreadId;
AttachThreadInput(PID,hCurThreadID,TRUE);
SetWindowPos(win_handle,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE or SWP_NOMOVE);
SetWindowPos(win_handle,HWND_NOTOPMOST,0,0,0,0,SWP_SHOWWINDOW or SWP_NOSIZE or SWP_NOMOVE);
SetForegroundWindow(win_handle);
SetFocus(win_handle);
SetActiveWindow(win_handle);
AttachThreadInput(PID,hCurThreadID,false);
{ Obtain stride value to allocate buffer }
HRCHECK(surface.LockRect(rc,nil,0));
pitch := rc.Pitch;
HRCHECK(surface.UnlockRect());
shot_size := pitch*mode.Height;
getmem(shot,shot_size);
if not assigned(shot) then abort;
try
{ get surface data }
HRCHECK(device.GetFrontBufferData(0, surface));
{ copy surface data }
HRCHECK(surface.LockRect(rc,nil,0));
move(rc.pBits^,shot^,shot_size);
HRCHECK(surface.UnlockRect());
{ save snapshot to file using WIC, using a temporary file name first }
var tmp_name := Tpath.GetTempFileName('png',false,image_folder);
if WICSavePixelsToPng(wr,pitch,shot,tmp_name) = S_OK then
begin
result := true;
{ rename temp file name to new name if it doesn't exist already }
var new_name := Tpath.ExtractDirectory(tmp_name) + THashSHA1.GetHashStringFromFile(tmp_name) + '.png';
if not TPath.FileExists(new_name) then
begin
if Tfile.Rename(tmp_name,new_name) then
begin
cs.file_path := '';
end else begin
cs.file_path := new_name;
end;
end else begin
cs.file_path := new_name;
end;
end;
Tfile.Delete(tmp_name);
finally
FreeMem(shot);
end;
except
result := false;
end;
end;
The limitation that I have with the D3D method is that in reality I don't take a snapshot of a specific window but I take a snapshot of the entire screen that I crop after to take only the window of my interest.
For that, I must bring first the target window to front, but in some case this may not be possible. For instance if the target form is behind a modal form, it might be partially or totally hidden, as one can see below
So, my question : Is it possible to take a snapshot / print a single Firemonkey 2D form from another process, even if the form is not modal / partially covered by another form.
(Sorry for an answer here rather than a comment, which I can't do.)
I know little about working with different processes, but do you realise that FMX has a snapshot ability built in?
TControl.MakeScreenshot returns a bitmap of the control (with child controls). So if you can call that from the other process and return the result, that might solve your problem.
However, this won't meet your needs if you literally need the whole form including the non-client area, as a form doesn't have that method. If the contents of the form are all you need, and you have a control (e.g. a TLayout) filling the form and containing all the child controls, you could use the .MakeScreenshot of that bottom control.
And yes, .MakeScreeshot works even if something else is covering the form.

Find HID/PID in DELPHI / ARDUINO Interface

(First, I am not sure whether this question is placed in the correct section of Stack Exchange. If not so, please give me a notice and delete the question.)
I have 8 Arduino's (Ards). Some Uno's and some 2650 Mega's. In an attempt to automatize the connection process (I use Delphi D-7 SE as I/O), I want to differentate between the UNO and the 2650 (mostly because the hardware differences in the appropriate chip). The way to do this (I think), is to get the PID and VID from the board. But I don't know how to do this. The code below gives me the correct driver, but not PID/VID . Is it possible to get PID/VID for this code-snippet ?? IF so, HOW ?
Thanks a lot.
Code here:
unit ArduinoTestU;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics,
Controls, Forms, Dialogs, JVsetupAPI, Registry, StdCtrls,
CPortCtl, CPort, Menus, XPMan;
type
TMainForm = class(TForm)
ListBox1: TListBox;
Label1: TLabel;
Button1: TButton;
procedure FormCreate(Sender: TObject);
function SetupEnumAvailableComPorts : TstringList;
procedure ListBox1Click(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
ArdType : Integer;
end;
var
MainForm : TMainForm;
ComPortStringList : TStringList;
MyComPort : String;
CurDir : String;
implementation
uses Form1Unit, ArdFormU; (* , ArdFormU; *)
{$R *.dfm}
procedure TMainForm.Button1Click(Sender: TObject);
begin
MainForm.FormActivate(NIL);
end;
procedure TMainForm.FormActivate(Sender: TObject);
var
index : integer;
begin
ComPortStringList := SetupEnumAvailableComPorts;
if (ComPortStringList <> nil) and (ComPortStringList.Count > 0) then
for Index := 0 to ComPortStringList.Count - 1 do
Listbox1.Items.Add(ComPortStringList[Index]);
if Listbox1.Items.Count <> 0 then
BEGIN
Listbox1.Enabled := True;
Button1.Enabled := False;
END;
end;
procedure TMainForm.FormCreate(Sender: TObject);
BEGIN
Curdir := ExtractFileDir(Application.Exename);
end;
(*
The function below returns a list of available COM-ports
(not open by this or an other process), with friendly names. The list is formatted as follows:
COM1: = Communications Port (COM1)
COM5: = NI Serial Port (Com5)
COM6: = NI Serial Port (Com6)
COM7: = USB Serial Port (COM7)
COM8: = Bluetooth Communications Port (COM8)
COM9: = Bluetooth Communications Port (COM9)
This code originally posted at http://www.delphi3000.com/articles/article_4001.asp?SK=
errors have been fixed so it will work with Delphi 7 and SetupAPI from JVCL
*)
function TMainForm.SetupEnumAvailableComPorts : TstringList;
//
// Enumerates all serial communications ports that are available and ready to
// be used.
//
var
RequiredSize: Cardinal;
GUIDSize: DWORD;
Guid: TGUID;
DevInfoHandle: HDEVINFO;
DeviceInfoData: TSPDevInfoData;
MemberIndex: Cardinal;
PropertyRegDataType: DWord;
RegProperty: Cardinal;
RegTyp: Cardinal;
Key: Hkey;
Info: TRegKeyInfo;
S1,S2: string;
hc: THandle;
begin
Result := Nil;
//
//If we cannot access the setupapi.dll then we return a nil pointer.
//
if not LoadsetupAPI then
exit;
try
//
// get 'Ports' class guid from name
//
GUIDSize := 1; // missing from original code - need to tell function that the Guid structure contains a single GUID
if SetupDiClassGuidsFromName('Ports',#Guid,GUIDSize,RequiredSize) then
begin
//
//get object handle of 'Ports' class to interate all devices
//
DevInfoHandle := SetupDiGetClassDevs(#Guid,Nil,0,DIGCF_PRESENT);
if Cardinal(DevInfoHandle) <> Invalid_Handle_Value then
begin
try
MemberIndex := 0;
result := TStringList.Create;
//iterate device list
repeat
FillChar(DeviceInfoData,SizeOf(DeviceInfoData),0);
DeviceInfoData.cbSize := SizeOf(DeviceInfoData);
//get device info that corresponds to the next memberindex
if Not SetupDiEnumDeviceInfo(DevInfoHandle,MemberIndex,DeviceInfoData) then
break;
//query friendly device name LIKE 'BlueTooth Communication Port (COM8)' etc
RegProperty := SPDRP_FriendlyName; {SPDRP_Driver, SPDRP_SERVICE, SPDRP_ENUMERATOR_NAME,SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,SPDRP_FRIENDLYNAME,}
SetupDiGetDeviceRegistryProperty(DevInfoHandle, DeviceInfoData,RegProperty, PropertyRegDataType,NIL,0,RequiredSize);
SetLength(S1,RequiredSize);
// ShowMessage('TEST: ' + S1);
if SetupDiGetDeviceRegistryProperty(DevInfoHandle,DeviceInfoData,RegProperty,PropertyRegDataType,#S1[1],RequiredSize,RequiredSize) then
begin
KEY := SetupDiOpenDevRegKey(DevInfoHandle,DeviceInfoData,DICS_FLAG_GLOBAL,0,DIREG_DEV,KEY_READ);
if key <> INValid_Handle_Value then
begin
FillChar(Info, SizeOf(Info), 0);
//query the real port name from the registry value 'PortName'
if RegQueryInfoKey(Key, nil, nil, nil, #Info.NumSubKeys,#Info.MaxSubKeyLen, nil, #Info.NumValues, #Info.MaxValueLen,
#Info.MaxDataLen, nil, #Info.FileTime) = ERROR_SUCCESS then
begin
RequiredSize := Info.MaxValueLen + 1;
SetLength(S2,RequiredSize);
if RegQueryValueEx(KEY,'PortName',Nil,#Regtyp,#s2[1],#RequiredSize) = Error_Success then
begin
If (Pos('COM',S2) = 1) then
begin
//Test if the device can be used
hc := CreateFile(pchar('\\.\' + S2 + #0), GENERIC_READ or GENERIC_WRITE,
0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if hc <> INVALID_HANDLE_VALUE then
begin
Result.Add(Strpas(PChar(S2)) + ' := ' + StrPas(PChar(S1)));
CloseHandle(hc);
end;
end;
end;
end;
RegCloseKey(key);
end;
end;
Inc(MemberIndex);
until False;
//If we did not found any free com. port we return a NIL pointer.
if Result.Count = 0 then
begin
Result.Free;
Result := NIL;
end
finally
SetupDiDestroyDeviceInfoList(DevInfoHandle);
end;
end;
end;
finally
UnloadSetupApi;
end;
end;
procedure TMainForm.ListBox1Click(Sender: TObject);
begin
Ardtype := Listbox1.ItemIndex;
MainForm.Hide;
ArdForm.ShowModal;
if Ardform.ModalResult <> mrOK then
ShowMessage('Der opstod en fejl ')
ELSE
BEGIN
MainForm.Show;
END;
end;
end.
Kris aka snestrup2016

How do I get the font name from a font file?

I want to enumerate all the file in the C:\Windows\Fonts\
First I use FindFirst&FindNext to get all the file
Code:
Path := 'C:\Windows\Fonts';
if FindFirst(Path + '\*', faNormal, FileRec) = 0 then
repeat
Memo1.Lines.Add(FileRec.Name);
until FindNext(FileRec) <> 0;
FindClose(FileRec);
it get some name like this tahoma.ttf which display Tahoma regular in windows font folder .
but how can I get that ?
second I why can't enumerate files in C:\Windows\Fonts\ by shell
Code :
var
psfDeskTop : IShellFolder;
psfFont : IShellFolder;
pidFont : PITEMIDLIST;
pidChild : PITEMIDLIST;
pidAbsolute : PItemIdList;
FileInfo : SHFILEINFOW;
pEnumList : IEnumIDList;
celtFetched : ULONG;
begin
OleCheck(SHGetDesktopFolder(psfDeskTop));
//Font folder path
OleCheck(SHGetSpecialFolderLocation(0, CSIDL_FONTS, pidFont));
OleCheck(psfDeskTop.BindToObject(pidFont, nil, IID_IShellFolder, psfFont));
OleCheck(psfFont.EnumObjects(0, SHCONTF_NONFOLDERS or SHCONTF_INCLUDEHIDDEN
or SHCONTF_FOLDERS, pEnumList));
while pEnumList.Next(0, pidChild, celtFetched ) = 0 do
begin
//break in here
pidAbsolute := ILCombine(pidFont, pidChild);
SHGetFileInfo(LPCTSTR(pidAbsolute), 0, FileInfo, SizeOf(FileInfo),
SHGFI_PIDL or SHGFI_DISPLAYNAME );
Memo1.Lines.Add(FileInfo.szDisplayName);
end;
end;
and I know use Screen.Fonts can get font list but it display different from C:\Windows\Fonts\;
The GetFontResourceInfo undocumented function can get the name of the font from a font file.
Try this sample
{$APPTYPE CONSOLE}
{$R *.res}
uses
Windows,
SysUtils;
function GetFontResourceInfo(lpszFilename: PChar; var cbBuffer: DWORD; lpBuffer: PChar; dwQueryType: DWORD): DWORD; stdcall; external 'gdi32.dll' name 'GetFontResourceInfoW';
procedure ListFonts;
const
QFR_DESCRIPTION =1;
var
FileRec : TSearchRec;
cbBuffer : DWORD;
lpBuffer: array[0..MAX_PATH-1] of Char;
begin
if FindFirst('C:\Windows\Fonts\*.*', faNormal, FileRec) = 0 then
try
repeat
cbBuffer:=SizeOf(lpBuffer);
GetFontResourceInfo(PWideChar('C:\Windows\Fonts\'+FileRec.Name), cbBuffer, lpBuffer, QFR_DESCRIPTION);
Writeln(Format('%s - %s',[FileRec.Name ,lpBuffer]));
until FindNext(FileRec) <> 0;
finally
FindClose(FileRec);
end;
end;
begin
try
ListFonts;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
About your second question
replace this line
while pEnumList.Next(0, pidChild, b) = 0 do
with
while pEnumList.Next(0, pidChild, celtFetched) = 0 do
I got this from a German Delphi forum. It works on Delphi 7 Enterprise.
function GetFontNameFromFile(FontFile: WideString): string;
type
TGetFontResourceInfoW = function(Name: PWideChar; var BufSize: Cardinal;
Buffer: Pointer; InfoType: Cardinal): LongBool; stdcall;
var
GFRI: TGetFontResourceInfoW;
AddFontRes, I: Integer;
LogFont: array of TLogFontW;
lfsz: Cardinal;
hFnt: HFONT;
begin
GFRI := GetProcAddress(GetModuleHandle('gdi32.dll'), 'GetFontResourceInfoW');
if #GFRI = nil then
raise Exception.Create('GetFontResourceInfoW in gdi32.dll not found.');
if LowerCase(ExtractFileExt(FontFile)) = '.pfm' then
FontFile := FontFile + '|' + ChangeFileExt(FontFile, '.pfb');
AddFontRes := AddFontResourceW(PWideChar(FontFile));
try
if AddFontRes > 0 then
begin
SetLength(LogFont, AddFontRes);
lfsz := AddFontRes * SizeOf(TLogFontW);
if not GFRI(PWideChar(FontFile), lfsz, #LogFont[0], 2) then
raise Exception.Create('GetFontResourceInfoW failed.');
AddFontRes := lfsz div SizeOf(TLogFont);
for I := 0 to AddFontRes - 1 do
begin
hFnt := CreateFontIndirectW(LogFont[I]);
try
Result := LogFont[I].lfFaceName;
finally
DeleteObject(hFnt);
end;
end; // for I := 0 to AddFontRes - 1
end; // if AddFontRes > 0
finally
RemoveFontResourceW(PWideChar(FontFile));
end;
end;
procedure TMainForm.btnFontInfoClick(Sender: TObject);
begin
if OpenDialog1.Execute then
MessageDlg(Format('The font name of %s is'#13#10'%s.', [OpenDialog1.FileName,
GetFontNameFromFile(OpenDialog1.FileName)]), mtInformation, [mbOK], 0);
end;
Here's an adaptation of RRUZ's answer with the benefit that you can enumerate and find the names of fonts in any directory, not necessarily only the installed fonts in C:\Windows. The trick is to call AddFontResource before (and RemoveFontResource after) processing it with GetFontResourceInfoW for each font file:
program font_enum;
{$APPTYPE CONSOLE}
{$R *.res}
uses
Windows,
System.SysUtils;
const
QFR_DESCRIPTION = 1;
var
p: String;
F: TSearchRec;
cbBuffer: DWORD;
lpBuffer: array [0 .. MAX_PATH - 1] of Char;
function GetFontResourceInfo(lpszFilename: PChar; var cbBuffer: DWORD; lpBuffer: PChar; dwQueryType: DWORD): DWORD;
stdcall; external 'gdi32.dll' name 'GetFontResourceInfoW';
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
p := ParamStr(1);
if (p = EmptyStr) then
p := ExtractFilePath(ParamStr(0))
else if (not DirectoryExists(p)) then
begin
Writeln('Directory specified is not valid.');
Exit;
end;
p := IncludeTrailingPathDelimiter(p);
if (FindFirst(p + '*.ttf', faAnyFile - faDirectory, F) = 0) then
begin
repeat
AddFontResource(PWideChar(p + F.Name));
cbBuffer := SizeOf(lpBuffer);
GetFontResourceInfo(PWideChar(p + F.Name), cbBuffer, lpBuffer, QFR_DESCRIPTION);
Writeln(Format('%s = %s', [F.Name, lpBuffer]));
RemoveFontResource(PWideChar(p + F.Name));
until (FindNext(F) <> 0);
end;
FindClose(F);
if (FindFirst(p + '*.fon', faAnyFile - faDirectory, F) = 0) then
begin
repeat
AddFontResource(PWideChar(p + F.Name));
cbBuffer := SizeOf(lpBuffer);
GetFontResourceInfo(PWideChar(p + F.Name), cbBuffer, lpBuffer, QFR_DESCRIPTION);
Writeln(Format('%s = %s', [F.Name, lpBuffer]));
RemoveFontResource(PWideChar(p + F.Name));
until (FindNext(F) <> 0);
end;
FindClose(F);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.

Creating a function to dig for Windows Handle by Classname(s) Only

So I just got an answer to my question about getting the Skype Chatbox handle.
I am now trying to create a simple function, that digs for a handle. Here is how I am hoping to be able to use it:
MyHWND := DigForHandle(['Notepad','Edit'],['Untitled - Notepad','']);
Params:
1) Array of String: Holds the Class Hierachy.
2) Array of String: Holds the Window Caption Hierachy.
As you see, the 2nd entry in the 2nd parameter is empty, since the Edit Class does not have a Window Caption.
Would it be possible to create such function? :)
Try this
uses
Windows, Messages, TlHelp32, SysUtils;
type
PGetWindowParam = ^TGetWindowParam;
TGetWindowParam = record
ProcID: DWORD;
WindowCaption: string;
Result: HWND;
end;
function DigForHandle(const ProcName, Caption: string; const Hierachy: array of string): HWND;
function FindPID(const ExeFileName: string): DWORD;
implementation
function FindPID(const ExeFileName: string): DWORD;
var
ContinueLoop: BOOL;
ProcessEntry32: TProcessEntry32;
SnapshotHandle: THandle;
TempExeFileName: string;
begin
Result := 0;
SnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if SnapshotHandle <> 0 then
begin
FillChar(ProcessEntry32, SizeOf(ProcessEntry32), 0);
ProcessEntry32.dwSize := Sizeof(ProcessEntry32);
ContinueLoop := Process32First(SnapshotHandle, ProcessEntry32);
while ContinueLoop do
begin
TempExeFileName := ExtractFileName(ProcessEntry32.szExeFile);
if SameText(TempExeFileName, ExeFileName) then
begin
Result := ProcessEntry32.th32ProcessID;
Break;
end;
ContinueLoop := Process32Next(SnapshotHandle, ProcessEntry32);
end;
CloseHandle(SnapshotHandle);
end;
end;
function GetWindow(Wnd: HWND; P: LParam): BOOL; stdcall;
var
Param: PGetWindowParam;
ProcID: DWORD;
WindowTitle: array[0..256] of Char;
begin
Result := True; // assume it doesn't match; keep searching
Param := PGetWindowParam(P);
ProcID := 0;
GetWindowThreadProcessID(Wnd, #ProcID);
if ProcID <> Param^.ProcID then
Exit;
FillChar(WindowTitle, SizeOf(WindowTitle), 0);
if SendMessage(Wnd, WM_GETTEXT, SizeOf(WindowTitle) - SizeOf(Char), LPARAM(#WindowTitle[0])) <= 0 then
Exit;
if AnsiSameStr(WindowTitle, Param^.WindowCaption) then
begin
Param^.Result := Wnd;
Result := False;
end;
end;
function DigForHandle(const ProcName, Caption: string; const Hierachy: array of string): HWND;
var
Param: TGetWindowParam;
I: Integer;
ParentWnd: HWND;
begin
Result := 0;
FillChar(Param, SizeOf(Param), 0);
Param.ProcID := FindPID(ProcName);
if Param.ProcID = 0 then
Exit;
Param.Result := 0;
Param.WindowCaption := Caption;
EnumWindows(#GetWindow, LPARAM(#Param));
if Param.Result = 0 then
Exit;
I := 0;
ParentWnd := Param.Result;
while (ParentWnd <> 0) and (I < Length(Hierachy)) do
begin
Param.Result := 0;
Param.WindowCaption := Hierachy[I];
EnumChildWindows(ParentWnd, #GetWindow, LPARAM(#Param));
if Param.Result = 0 then
Break;
ParentWnd := Param.Result;
Inc(I);
end;
if I >= Length(Hierachy) then
Result := Param.Result;
end;
When I thought about it, I realized that it was actually rather simple - the code I had though, was "confusing" for me, which was why I asked a question here. After trying it out, I found that doing it this way, its a lot easier to read, and not as complicated (IMO).
Function DigForHandle(ClassHierachy, TextHierachy : Array of String):HWND;
Var
Handle : HWND;
I : Integer;
PClass,PText : PChar;
Begin
Result := 0;
I := 0;
while (I <= Length(ClassHierachy)-1) do
begin
PClass := PChar(ClassHierachy[I]);
PText := PChar(TextHierachy[I]);
if PClass = '' then PClass := Nil;
if PText = '' then PText := Nil;
Result := FindWindowEx(Result,0,PClass,PText);
Inc(I);
end;
End;

How to get MAC address in windows7? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
Getting Machine’s MAC Address — Good Solution?
How do I get the MAC address of a network card using Delphi?
I am using MAC address as hardware id for protection(ofcourse I have encrypted this data)
I am using below code to get MAC address on user computer
function MacAddress: string;
var
Lib: Cardinal;
Func: function(GUID: PGUID): Longint; stdcall;
GUID1, GUID2: TGUID;
begin
Result := '';
Lib := LoadLibrary('rpcrt4.dll');
if Lib <> 0 then
begin
#Func := GetProcAddress(Lib, 'UuidCreateSequential');
if Assigned(Func) then
begin
if (Func(#GUID1) = 0) and
(Func(#GUID2) = 0) and
(GUID1.D4[2] = GUID2.D4[2]) and
(GUID1.D4[3] = GUID2.D4[3]) and
(GUID1.D4[4] = GUID2.D4[4]) and
(GUID1.D4[5] = GUID2.D4[5]) and
(GUID1.D4[6] = GUID2.D4[6]) and
(GUID1.D4[7] = GUID2.D4[7]) then
begin
Result :=
IntToHex(GUID1.D4[2], 2) + '-' +
IntToHex(GUID1.D4[3], 2) + '-' +
IntToHex(GUID1.D4[4], 2) + '-' +
IntToHex(GUID1.D4[5], 2) + '-' +
IntToHex(GUID1.D4[6], 2) + '-' +
IntToHex(GUID1.D4[7], 2);
end;
end;
end;
end;
above code works perfectly on windows XP
but its giving different values in windows7 ,the value changing every time after computer resratred :(
is there any chance of getting MAC address thats constant (unless user changed his MAC address)
or is there any good code which retrvies constant data on all OS ?
thanks in advance
#steve0, to retrieve the mac address of an Network Adapter you can use the WMI and the Win32_NetworkAdapterConfiguration Class and check the MACAddress property.
Check this code:
program WMI_MAC;
{$APPTYPE CONSOLE}
uses
SysUtils
,ActiveX
,ComObj
,Variants;
function VarToStrNil(Value:Variant):string; //Dummy function to onvert an variant value to string
begin
if VarIsNull(Value) then
Result:=''
else
Result:=VarToStr(Value);
end;
Procedure GetMacAddress;
var
objWMIService : OLEVariant;
colItems : OLEVariant;
colItem : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
wmiHost, root, wmiClass: string;
function GetWMIObject(const objectName: String): IDispatch;
var
chEaten: Integer;
BindCtx: IBindCtx;//for access to a bind context
Moniker: IMoniker;//Enables you to use a moniker object
begin
OleCheck(CreateBindCtx(0, bindCtx));
OleCheck(MkParseDisplayName(BindCtx, StringToOleStr(objectName), chEaten, Moniker));//Converts a string into a moniker that identifies the object named by the string
OleCheck(Moniker.BindToObject(BindCtx, nil, IDispatch, Result));//Binds to the specified object
end;
begin
wmiHost := '.';
root := 'root\CIMV2';
wmiClass := 'Win32_NetworkAdapterConfiguration';
objWMIService := GetWMIObject(Format('winmgmts:\\%s\%s',[wmiHost,root]));
colItems := objWMIService.ExecQuery(Format('SELECT * FROM %s',[wmiClass]),'WQL',0);
oEnum := IUnknown(colItems._NewEnum) as IEnumVariant;
while oEnum.Next(1, colItem, iValue) = 0 do
//if VarToStrNil(colItem.MACAddress)<>'' then //uncomment if you only want list the interfaces with mac adress
//if colItem.IPEnabled then // uncomment if you only want list the active interfaces
begin
WriteLn('Card Description '+VarToStrNil(colItem.Caption));
WriteLn('MACAddress '+VarToStrNil(colItem.MACAddress));
end;
end;
begin
try
CoInitialize(nil);
try
GetMacAddress;
Readln;
finally
CoUninitialize;
end;
except
on E:Exception do
Begin
Writeln(E.Classname, ': ', E.Message);
Readln;
End;
end;
end.
Here is some code working well for any computer on your network - may try it to get your own, using '127.0.0.1' as IP:
function GetRemoteMacAddress(const IP: AnsiString): TSockData;
// implements http://msdn.microsoft.com/en-us/library/aa366358(VS.85).aspx
type
TSendARP = function(DestIp: DWORD; srcIP: DWORD; pMacAddr: pointer; PhyAddrLen: Pointer): DWORD; stdcall;
const
HexChars: array[0..15] of AnsiChar = '0123456789ABCDEF';
var dwRemoteIP: DWORD;
PhyAddrLen: Longword;
pMacAddr : array [0..7] of byte;
I: integer;
P: PAnsiChar;
SendARPLibHandle: THandle;
SendARP: TSendARP;
begin
result := '';
SendARPLibHandle := LoadLibrary('iphlpapi.dll');
if SendARPLibHandle<>0 then
try
SendARP := GetProcAddress(SendARPLibHandle,'SendARP');
if #SendARP=nil then
exit; // we are not under 2K or later
dwremoteIP := inet_addr(pointer(IP));
if dwremoteIP<>0 then begin
PhyAddrLen := 8;
if SendARP(dwremoteIP, 0, #pMacAddr, #PhyAddrLen)=NO_ERROR then begin
if PhyAddrLen=6 then begin
SetLength(result,12);
P := pointer(result);
for i := 0 to 5 do begin
P[0] := HexChars[pMacAddr[i] shr 4];
P[1] := HexChars[pMacAddr[i] and $F];
inc(P,2);
end;
end;
end;
end;
finally
FreeLibrary(SendARPLibHandle);
end;
end;
This code is extracted from our freeware and open source framework, unit SynCrtSock.pas. See http://synopse.info/fossil

Resources