I've recently had a customer report an issue with my applications and NVidia nView desktop manager. Basically nView seems to 'unhide' hidden secondary forms when moving an application between monitors. I'm testing with Delphi 2010. The problem can also be seen using just the IDE (show a non-docked window, close it and then choose to send the Delphi IDE to a different monitor.) The previously hidden forms are in an unresponsive state and can't be closed.
To reproduce:
. Use a multi-monitor system with NVidia nView desktop manager.
. Start any Delphi application with secondary forms that will be hidden when they are closed.
. Show or ShowModal the form, then close it (form needs to have been shown at least once).
. Choose to send the application to a different monitor. (via hotkeys or the caption icons)
. The application will move to the other monitor and any hidden forms will be visible.
Has anyone else seen this issue? I've verified it with an older version of nView, but a customer with the latest version has the issue whenever he tries to move the main form or resize it. Unfortunately my laptop can't be updated to the latest version so I can't easily test with it.
Thanks for any comments or suggestions!
-Mark
I had the same problem. The Delphi application stopped responding without any obvious reason. Looking at the stack trace from madExcept I could see that the application froze in nview.dll. The only "solution" that I found was to look for nView and advise the user to turn it off using the code below:
function CheckForNview: Boolean;
function IsNviewModuleRunning(AHandle: THandle; AProcessId: DWord): Boolean;
var
AModuleEntry: TModuleEntry32;
begin
AModuleEntry.dwSize := SizeOf(AModuleEntry);
AModuleEntry.th32ProcessID := AProcessId;
Result := False;
if Module32First(AHandle, AModuleEntry) then
begin
if SameStr(AModuleEntry.szModule, 'nview.dll') then
Result := True;
while Module32Next(AHandle, AModuleEntry) do
begin
if SameStr(AModuleEntry.szModule, 'nview.dll') then
Result := True;
end;
end;
end;
var
AHandle: THandle;
AProcessEntry: TProcessEntry32;
begin
Result := False;
AHandle := CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
if Process32First(AHandle, AProcessEntry) then
begin
if SameStr(AProcessEntry.szExeFile, ExtractFileName(ParamStr(0))) then
Result := Result or IsNviewModuleRunning(AHandle, AProcessEntry.th32ProcessID);
while Process32Next(AHandle, AProcessEntry) do
begin
if SameStr(AProcessEntry.szExeFile, ExtractFileName(ParamStr(0))) then
Result := Result or IsNviewModuleRunning(AHandle, AProcessEntry.th32ProcessID);
end;
end;
Related
I'm using Delphi XE5.
On my GroupFooter I try to hide several memos in a conditional is met
procedure GroupFooter1OnBeforePrint(Sender: TfrxComponent);
begin
ShowMessage('a');
if <frxDB."total_payment"> <= 0 then begin
Memo27.Visible := False;
Memo28.Visible := False;
Memo29.Visible := False;
Memo30.Visible := False;
end;
end;
This is my calling code in Delphi
Report.LoadFromFile(CurDir+'reports/invoice/'+ReportName);
if Report.PrepareReport then
Report.ShowPreparedReport;
I found that the OnBeforePrint event never fires when the report was showing after frxReport.ShowPreparedReport command, but when I tries to preview it in the designer, it works just as normal.
I keep wondering what did I miss.
Anyone can help?
Thanks
I recently found out that this is due to FastReport 4 demo version that is bundled along with Embarcadero RAD Studio XE5. The full version works perfectly, but any fr3 file created from demo-bundled version can't be opened in full version.
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.
I need to send several virtual keys (VK_RETURN) from my delphi application (myapp.exe) into another application (target.exe).
Eg : Send VK_RETURN twice , from myapp.exe , into target.exe
The OS that I use are Windows 7 64 bit and Windows XP.
I read : How to send an "ENTER" key press to another application? , Send Ctrl+Key to a 3rd Party Application (did not work for me) and other previous asked question.
But still I'm getting confused.
How to set the focus to the target application ?
How to send the virtual keys to the targeted application ?
Simple example : I want to send VK_RETURN twice into notepad.exe or calc.exe (already loaded) or any other program from my delphi application. How to do that ?
The simplest way to do this in Delphi 2010, please...
PS :
I tried SndKey32.pass from http://delphi.about.com/od/adptips2004/a/bltip1104_3.htm
And got error : [DCC Error] SndKey32.pas(420): E2010 Incompatible types: 'Char' and 'AnsiChar'
If (Length(KeyString)=1) then MKey:=vkKeyScan(KeyString[1])
If your target application isn't the foreground window, you need to use PostMessage to send keystrokes to its window handle. You can get that window handle using FindWindow. The code below sends the Enter key to a the text area in a running instance of Notepad (note it uses an additional FindWindowEx to locate the memo area first). It was tested using both Delphi 2007 and Delphi XE4 (32-bit target) on Windows 7 64.
uses Windows;
procedure TForm1.Button1Click(Sender: TObject);
var
NpWnd, NpEdit: HWnd;
begin
NpWnd := FindWindow('Notepad', nil);
if NpWnd <> 0 then
begin
NpEdit := FindWindowEx(NpWnd, 0, 'Edit', nil);
if NpEdit <> 0 then
begin
PostMessage(NpEdit, WM_KEYDOWN, VK_RETURN, 0);
PostMessage(NpEdit, WM_KEYUP, VK_RETURN, 0);
end;
end;
end;
To find the window by title (caption) instead, you can just use the second parameter to FindWindow. This finds a new instance of Notepad with the default 'Untitled' file open:
NpWnd := FindWindow(nil, 'Untitled - Notepad');
Note that this requires as exact match on the window title. An extra space before or after the -, for instance, will cause the match to fail and the window handle to not be retrieved.
You can use both the window class and title if you have multiple instances running. To find the copy of Notepad running with Readme.txt loaded, you would use
NpWnd := FindWindow('Notepad', 'Readme.txt - Notepad');
To find other applications, you'll need to use something like WinSpy or WinSight to find the window class names. (There are others also, such as Winspector or WinDowse (both of which are written in Delphi).)
Your comment mentions Calculator; according to Winspector, the Calculator main window is in a window class called CalcFrame on Windows 7, and the area the numbers are displayed in is a Static window (meaning it doesn't seem to receive keystrokes directly). The buttons are simply called Button, so you'd have to loop through them using EnumChildWindows looking for the individual buttons to identify them in order to obtain their handles.
(How to enumerate child windows is a separate question; you can probably find an example by searching here or via Google. If you can't, post a new, separate question about that and we can try to get you an answer.)
Here's a quick example of sending keys to Calculator after finding it by window class. It doesn't do anything useful, because it needs some time spent to identify different buttons and the keys that each responds to (and the proper combination of messages). This code simply sends 11Numpad+22 to the calculator window (a quick test showed that they were properly received and displayed, and that's about all the time I wanted to spend on the process).
uses Windows;
procedure TForm1.Button1Click(Sender: TObject);
var
NpWnd: HWnd;
begin
NpWnd := FindWindow('CalcFrame', nil);
if NpWnd <> 0 then
begin
PostMessage(NpWnd, WM_KEYDOWN, VK_NUMPAD1, 0);
PostMessage(NpWnd, WM_KEYDOWN, VK_ADD, 0);
PostMessage(NpWnd, WM_KEYDOWN, VK_NUMPAD2, 0);
end;
end;
I've run into the following problem:
My Delphi7 program runs smoothly on most computers running WinXP/Vista/7 BUT on some older Windows XP installs (only a few) I'm getting the following problem:
I have a system image list, and I'm adding my own icons to a copy of the system image list. Upon adding my icons I get an "Invalid image size." EInvalidOperation error.
Here is the code in question:
function GetSystemLargeIconsList: TCustomImageList;
// This gets the system image list.
var
SysIL: HImageList;
SFI: TSHFileInfo;
MyImages: TCustomImageList;
begin
SysIL := SHGetFileInfo('', 0, SFI, SizeOf(SFI),
SHGFI_SYSICONINDEX or SHGFI_LARGEICON);
if SysIL <> 0 then begin
MyImages:=TCustomImageList.Create(nil);
// Assign the system list to the component
MyImages.Handle := SysIL;
// The following prevents the image list handle from being
// destroyed when the component is.
MyImages.ShareImages := TRUE;
Result:=MyImages;
end;
end;
var
DocumentImgList: TCustomImageList;
IconToAdd: TIcon;
begin
DocumentImgList:=GetSystemLargeIconsList;
Documents.LargeImages:=DocumentImgList;
Documents.SmallImages:=DocumentImgList;
IconToAdd:=TIcon.Create;
DocumentListIcons.GetIcon(0, IconToAdd);
DocumentImgList.AddIcon(IconToAdd); ----> this is the line of the exception
To make the problem worse, I'm using the TPngImageList component, but according to the code, it just seems to call the standard Delphi function:
if TObject(Self) is TPngImageList
then if Image = nil
...
else begin
Patch := FindMethodPatch('AddIcon');
if Patch <> nil
then begin
Patch.BeginInvokeOldMethod;
try
Result := TCustomImageList(Self).AddIcon(Image); ----> this is where the exception happens
finally
Patch.FinishInvokeOldMethod;
end;
end
else Result := -1;
end;
I've recently found out that on one of the computers that have this problem, either uxtheme.dll or explorer.exe has been patched with some Windows-skinning program.
So I suppose that somebody or a program is hacking the system image list in a way that is making my Delphi program crash.
Any ideas on how to fix this?
Thanks!
One thing you could try would be to load your icon into a separate tBitmap, then resize it before adding it into the image list.
I did a checkout of d-gecko SDK from sf.net ( http://sourceforge.net/projects/d-gecko/ ).
I wanted to try it with Gecko (XULRunner) 1.9, however when running simple application each time I get error in stdcall function, pointing to WebBrowser.Paint line ...
My question is - did anyone succeeded to run GeckoSDK Delphi app in XULRunner 1.9?
If so - how? Did it worked out-of-the-box for you?
Thanks
m.
You need to navigate somewhere before the webbrowser first attempts to paint itself. So, LoadURI() must be called before the component is visible.
Easiest solution: Call LoadURI('about:blank') before the component is visible.
I had also this problem. I just neutralized baseWin.Repaint(True);
Il all worked perfectly afterward
procedure TCustomGeckoBrowser.Paint;
var
rc: TRect;
baseWin: nsIBaseWindow;
begin
if csDesigning in ComponentState then
begin
rc := ClientRect;
Canvas.FillRect(rc);
end else
begin
baseWin := FWebBrowser as nsIBaseWindow;
//baseWin.Repaint(True);
end;
inherited;
end;