WIA 2 on Windows 7 -- Delphi - delphi

WIA 2 on Windows 7 doesn't detect my camera while WIA 1 on Windows XP detects it.
I try to run my program as admin.
My camera is :
Asus usb2 webcam.
Delphi return the message:
(like this) not available any wia devices from specified type
or
Access Violation at address ...... in module ......
I use this code:
procedure TForm1.Button9Click(Sender: TObject);
Const
wiaFormatBMP ='{B96B3CAB-0728-11D3-9D7B-0000F81EF32E}';
var
CommonDlg: ICommonDialog;
AImage: IImageFile;
ImagePath: String;
DeviceManager1 :iDeviceManager;
begin
CommonDlg := createOleObject('WIA.CommonDialog') as ICommonDialog;
DeviceManager1 := createOleObject('WIA.DeviceManager') as iDeviceManager;
edit1.Text:= inttostr( DeviceManager1.DeviceInfos.Count);
AImage := CommonDlg.ShowAcquireImage(UnspecifiedDeviceType,UnspecifiedIntent,
MaximizeQuality,wiaFormatBMP,true,False,True);
ImagePath := 'C:\temp\test.bmp';
AImage.SaveFile(ImagePath);
end;

I recently had a similar experience with WIA and Win7.
What I eventually ended up using was a DirectX solution.
Delphi Basics - DirectX webcam capture
I don't remember how I originally found this project, but under Win7 it just works even with older webcams that I found lying around the office.
I recommend you look at Demo3 in the download file as that had the best, simple, example of what I needed. YMMV.
(Edit) My WIA problem extended from the fact that the webcam maker did not support WIA or Twain under Win7.

Related

Scaling of coordinates between different screen resolutions

I have projects developed in Delphi 10 on a laptop with a screen resolution of 96. I am now using Delphi 10.4 Community Edition on a Microsoft Surface with a screen resolution of 201. Is there a function or a settings that automatically converts numerically defined coordinates when scaling an application? To show what I mean I add this code snippet.
procedure TForm1.Button1Click(Sender: TObject);
begin
with Canvas do
begin
MoveTo(0,0);
LineTo(400,250);
MoveTo(0,0);
LineTo(ClientWidth,ClientHeight);
end;
end;
The first line drawn does not scale, the second one obviously does.
May I add:
If I compile the same code on my old laptop with a screen resolution of 96 and then run the exe file on my Surface Laptop with a screen resolution of 201 it scales ok, I was hoping there was a facility somewhere to compile my old programmes on my new computer without having to manually change all the code referring to coordinates x and y.
There's no built-in scaling of coordinates in a TCanvas. You can use this CLASS HELPER:
TYPE
TFormHelper = CLASS HELPER FOR TForm
FUNCTION Scale(Value : INTEGER) : INTEGER;
END;
FUNCTION TFormHelper.Scale(Value : INTEGER) : INTEGER;
BEGIN
Result:=MulDiv(Value,CurrentPPI,Screen.DefaultPixelsPerInch)
END;
Use it as in:
procedure TForm1.Button1Click(Sender: TObject);
begin
with Canvas do
begin
MoveTo(Scale(0),Scale(0)); // Not needed, as 0 scaled is always 0, but... //
LineTo(Scale(400),Scale(250));
MoveTo(0,0);
LineTo(ClientWidth,ClientHeight);
end;
end;
To run my projects developed with Delphi 10 on my new computer with a higher screen resolution, using Delphi 10.4 Community Edition I change the setting
Project Options -> Application -> Manifest -> DPI Awareness to GDI Scaling and it all works like a charm.

Delphi 5 : Total number of page in pdf

I am maintaining an old application that is built with Delphi 5.
I need to determine the total number of pages in a given pdf file.
I guess I could translate any solution for plain C also.
The current solution I have is forking a pdftk process, and parse its output. But this is quite slow, so I was wondering if I could find a good open-source pdf parser library for delphi (5...)... And it seems it doesn't exist.
So I tried to implement things like looking into the file's raw content for occurences of "/Type /Page" or "/Count" or "Linearized ... /N". But none of these -nor a combination of them- work in every case.
So I wondered if I could find an open-source DLL that I could make use of from Delphi 5. But I couldn't find any neither. I stumbled upon iTextSharp but it is for .NET and I don't understand howto use it in a plain delphi5 program...
So my final thought is this : is there any change I could find the source code for -say- pdftk and compile it as a DLL? Could anyone point me to the right direction?
Is there any solution I am missing?
I thank you in advance for your help!
Did you try to use the PDFLib dll?
It is a very efficient library, and they have binding for Delphi, either via COM or via their dll. I guess you could use Delphi 5 with this library.
Did you try to run the free pdfinfo tool?
Download it from http://www.foolabs.com/xpdf
It returns such information:
Title: Optimizing software in C++
Keywords: software C++ optimization compiler
Author: Agner Fog
Creator: Microsoft® Word 2013
Producer: Microsoft® Word 2013
CreationDate: 12/15/14 14:25:13
ModDate: 12/15/14 14:25:13
Tagged: yes
Form: none
Pages: 37
Encrypted: no
Page size: 595.32 x 841.92 pts (A4) (rotated 0 degrees)
File size: 531693 bytes
Optimized: no
PDF version: 1.5
So here you have your number of pages.
And it is very fast.
If you install adobe acrobat (not reader) on user's PC then you can use OLE automation.
Here example how to open file and read pages count:
uses
ComObj, ActiveX;
function TmyForm.IsOLEObjectInstalled(Name: String): Boolean;
var
ClassID: TCLSID;
Rez: HRESULT;
begin
Rez := CLSIDFromProgID(PWideChar(WideString(Name)), ClassID);
Result := (Rez = S_OK);
end;
procedure TmyForm.ButtonCheckPagesClick(Sender: TObject);
var
doc: OleVariant;
pagesCount: Integer;
begin
if IsOLEObjectInstalled('AcroExch.PDDoc') then
begin
doc := CreateOleObject('AcroExch.PDDoc');
if doc.Open('C:\test\test.pdf') then
begin
pagesCount := doc.GetNumPages;
ShowMessageFmt('pages count = %d', [pagesCount]);
end
else
begin
ShowMessage('Can''t open file');
end;
end
else
begin
ShowMessage('You must install adobe acrobat for that feature');
end;
end;

How to make hovering over Minimize, Maximize, and Close buttons behave?

In a Delphi application, when you hover over a border icon, e.g.:
Minimize
Maximize
Restore
it doesn't behave correctly:
Compare to an application that does behave correctly:
Step to Reproduce
Click File, New, VCL Forms Application - Delphi
Click Run (F9)
Hover over the Minimize, Maximize, or Close buttons.
How to fix?
Windows 10, 64-bit (running natively on desktop PC)
Delphi XE6
Edit - It also fails with Delphi 7:
and in Delphi 5:
and in Delphi 4:
I assumed (i.e. was afraid) that it was caused by the ThemeServices engine; where they might have thought it was cool to not honor the user's preferences. But looks like it's something more fundamental.
Compatibility Modes
none: fails
Windows 8: fails
Windows 7: fails
Windows Vista (Service Pack 2): fails
Windows Vista (Service Pack 2): fails
Windows Vista: fails
Windows XP (Service Pack 3) (non-client area theming disabled): works
Windows XP (Service Pack 2) (non-client area theming disabled): works
Windows 98 / Windows Me (non-client area theming disabled): works
Windows 95 (non-client area theming disabled): works
Skype
Also fails in Skype; also written in Delphi:
High DPI is the trigger
I finally figured out why it fails on every Windows 10 machine i've used; but not for everyone. High dpi.
Set your dpi to 97 (101%) or higher.
Close Enough
Dalija's solutions works:
We'll ignore the problem with the tooltip and live to fight another day.
It should also be noted that Windows 10 will suggest that you might have to sign off and sign back on for some applications to work correctly after changing the DPI. This is definitely true of Delphi.
It should also be noted that Delphi doesn't tolerate the DPI changing behind its back like this. This includes adjusting the zoom slider. This would also include placing the app on any monitor besides the primary monitor.
And we never did figure out what the problem is; only kicked it down the road for users running multiple monitors.
QC Bug Report
Because Bor...Impr...CodeG...Embarca... Idera's QC site is behind a pay-wall, here's a copy of the bug report:
http://archive.is/v77rz
As you can see: nobody cares.
High DPI is the trigger and it leads to the solution.
Applications that exhibit the issue are not High DPI aware. Solution to hovering problem is to make them aware or turn on associated compatibility mode by using one of solutions under 1, 2 or 3.
Note: whether will rest of the application behave properly when High DPI awareness is turned on is another issue and will differ from application to application.
Under compatibility mode check "Disable display scaling on high DPI settings"
Call SetProcessDPIAware as first call in .dpr file - as noted by Ian Boyd, calling this function can leat to race condition and preferred way is using manifest. SetProcessDPIAware
Use custom manifest with true or true/PM setting (default Delphi manifest included with "Enable runtime themes" is not high DPI aware)
Current versions of Delphi VCL and FMX frameworks lack support for per monitor DPI awareness, so use true/PM manifest only if you are handling per monitor DPI yourself. Reported to QP as VCL and FireMonkey lack Per-Monitor DPI support for Windows 8.1 (and Windows 10)
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
or
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true/PM</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
Update:
Delphi VCL is source of buggy behavior, specifically issue is somewhere in TForm class or its ancestors. When direct Windows API is used resulting windows behave normally.
Windows API code that behaves properly:
MessageBox(0, 'Correct', 'Caption', MB_OK);
ShowMessage('Correct'); // if themes are enabled -> Windows Task dialog is used
Full Delphi sample app that creates main window without using VCL - behaves properly
program win;
{$R *.res}
uses
Windows,
Messages,
SysUtils;
var
Msg: TMSG;
LWndClass: TWndClass;
hMainHandle: HWND;
function WindowProc(HWND, Msg: Longint; wParam: wParam; lParam: lParam): Longint; stdcall;
begin
if Msg = WM_DESTROY then PostQuitMessage(0);
Result := DefWindowProc(HWND, Msg, wParam, lParam);
end;
begin
LWndClass.hInstance := hInstance;
with LWndClass do
begin
lpszClassName := 'WinApiWnd';
Style := CS_PARENTDC or CS_BYTEALIGNCLIENT;
hIcon := LoadIcon(hInstance, 'MAINICON');
lpfnWndProc := #WindowProc;
hbrBackground := COLOR_BTNFACE + 1;
hCursor := LoadCursor(0, IDC_ARROW);
end;
RegisterClass(LWndClass);
hMainHandle := CreateWindow(LWndClass.lpszClassName, 'Window Title', WS_CAPTION or WS_MINIMIZEBOX or WS_SYSMENU or WS_VISIBLE, 0, 0, 360, 200, 0, 0, hInstance, nil);
while GetMessage(Msg, 0, 0, 0) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end.
Misbehaved VCL forms:
var
f: TForm;
f := CreateMessageDialog('Broken', mtWarning, mbOKCancel, mbOk);
f.ShowModal;
f.Free;
f := TForm.Create(nil);
f.ShowModal;
f.Free;

Delphi Webcam Snapshot [duplicate]

This question already has answers here:
How to get a snapshot from a webcam with Delphi7 using VFrames(TVideoImage)
(2 answers)
Closed 8 years ago.
I need to find a foolproof way with Delphi XE to take a snapshot using a webcam and save it as a picture file. There are many posts about this but none of them work for me. Either the code won't compile or the image is not created. The best one so far is this one using VFrames. It shows the web cam video perfectly but when I try to save a snapshot to a bmp using the code below the image is blank white. I tried assigning it to a TImage with the same result. Does anyone know why this happens or have a better way to do this?
procedure TForm1.Button2Click(Sender: TObject);
var
cam:TVideoImage;
strlst:TStringList;
BMP:TBitmap;
begin
strlst := TStringList.Create ;
cam :=TVideoImage.Create;
cam.GetListOfDevices(strlst);
cam.VideoStart(strlst.Strings[0]); //specify a cam by number
//get snapshot
BMP := TBitmap.Create;
cam.GetBitmap(BMP);
BMP.SaveToFile('C:\test.bmp');
cam.VideoStop;
BMP.Free;
end;
I Think you should have a look a DirectX and I think you should have a look at this site :
http://www.delphibasics.info/home/delphibasicsprojects/directxdelphiwebcamcaptureexample
This page offers a great way to use webcams under windows, its very reliable and allows you to set any cam property. Its all opensource, easy to use and based on native windows DirectX libraries.
Use this sample:
http://www.delphibasics.info/home/delphibasicsprojects/directxdelphiwebcamcaptureexample/DirectXDelphiWebcamCapture.rar
This is a directX conversion to pascal made by michael#grizzlymotion.com
add VSample.pas and VFrames.pas to your project
uses VFrames;
procedure TForm6.Button1Click(Sender: TObject);
var
cam:TVideoImage;
strlst:TStringList;
begin
strlst := TStringList.Create ;
cam := TVideoImage.Create;
cam.GetListOfDevices(strlst);
cam.SetDisplayCanvas(PaintBox1.Canvas);
cam.VideoStart(strlst.Strings[0]) ;//specify your cam by number
end;
Or you can have a look at this : http://sourceforge.net/projects/webcam-cap/ it uses pure API calls to AVICAP32.DLL

How to use Delphi standard confirmation dialog but with checkbox "Don't ask me again"?

In many confirmation dialogs it is usefull to have such option (quick wayt to disable confirmation).
But i can't find how to do that. I don't want to design it myself because i need this dialog to be standard-like and don't wont to redesign with every update of Delphi. Is there simple way to use Delphi standard confirmation dialog with such checkbox ?
UPDATE2. Suggested SynTaskDialog library from Synopse project does great job (all i need and even more), i will use it in my projects. Thanks!
UPDATE. So, thank you guys for ideas. System function MessageBoxCheck is nice solution but seem to be not so stable as it should be. In general i agree that it is good idea to use latest API functions to provide users with best UI experience of modern os and use old-fashioned design for older systems. At moment i stay on simple solution (code is following), but if someone share the code with support of UI for modern OS, it will be nice.
function MsgDlgWithCB(const Msg,Title,CBMsg: string; DlgType: TMsgDlgType;
Buttons: TMsgDlgButtons; DefaultButton: TMsgDlgBtn;
var cbDontAskAnymore: TCheckBox): TForm;
var
i: integer;
b: TButton;
y: integer;
begin
Result := CreateMessageDialog(Msg, DlgType, Buttons, DefaultButton) ;
Result.Position := poScreenCenter;
cbDontAskAnymore := TCheckBox.Create(Result);
cbDontAskAnymore.Caption := CBMsg;
cbDontAskAnymore.Width := 130;
y := -1;
for i := 0 to result.ComponentCount-1 do
if result.Components[i] is TButton then
begin
b := TButton(result.Components[i]);
b.Left := b.Left + cbDontAskAnymore.Width + 16;
Result.ClientWidth := Max(Result.ClientWidth, b.Left+b.Width+16);
y := b.Top+b.Height-cbDontAskAnymore.Height;
end;
if y<0 then
y := Result.ClientHeight - cbDontAskAnymore.height - 16;
Result.Caption := Title;
cbDontAskAnymore.Parent := Result;
cbDontAskAnymore.Top := y;
cbDontAskAnymore.Left := 8;
end;
function MessageDlgCheckbox(const Msg: string; DlgType: TMsgDlgType;
Buttons: TMsgDlgButtons; DefaultButton: TMsgDlgBtn;
var cbDontAskAnymore: Boolean;
const Title: string ='Confirmation';
const CBMsg: string = 'Don''t ask anymore'): integer;
var
f: TForm;
c: TCheckbox;
begin
f := MsgDlgWithCB(Msg,Title,CBMsg,DlgType,Buttons,DefaultButton,c);
try
result := f.ShowModal;
cbDontAskAnymore := c.Checked;
finally
f.free;
end;
end;
You can use our Open Source SynTaskDialog unit.
Windows provides a generic task dialog available since Vista/Seven. But there is none available with previous versions of Windows, i.e. Windows XP or 2K.
This unit (licensed under a MPL/GPL/LGPL tri-license) will use the new TaskDialog API under Vista/Seven, and emulate it with pure Delphi code and standard themed VCL components under XP or 2K. It supports Delphi 6 up to XE4, and is Win32/Win64 Unicode ready.
Here is the result under a Windows Seven 64 bit computer:
And here is the same dialog created from our emulated pure Delphi code:
Since this screenshot was made on a Win 7 machine, the styling is native for that OS. When the emulated version of the dialog runs on XP it displays in a style native to that OS.
You have your "Do not ask for this setting next time" checkbox... and potentially much more!
The system native functionality that offers such facilities is the task dialog API introduced in Vista. This provides means for you to show much more capable dialogs than the older MessageBox API.
Should you need to support XP then you will have to create your own dialog. For example by deriving from TForm and calling ShowModal. If you do this, make the form capable of building itself dynamically. Don't make one form per message that you show!
In my codebase, I have my own wrapper of the task dialog API. This detects at runtime versions of Windows that do not support task dialog and falls back on a custom built Delphi dialog.
Regarding SHMessageBoxCheck I'd be a little wary of taking a dependency on that. According to its documentation it's not supported beyond XP, and you have to import it by ordinal. I'd personally be worried that it might be dropped from a future version of Windows. That said, MS has a strong track record of doing whatever it takes to keep legacy apps working with new OS releases.

Resources