I'm running into a very strange problem with the Vcl.FileCtrl function SelectDirectory (which is a thin wrapper around the ShBrowseForFolder Win32 API).
I'm using the following code to allow the user to browse for a file or a folder:
if SelectDirectory('Sélectionnez un élément à ajouter :', '', S, [sdNewFolder,
sdShowFiles, sdNewUI]) then
When executing this code, the "Browse for folder" dialog is correctly shown, displaying the content of the user's Desktop:
But when the number of items in the Desktop folder is excessively large (on my computer, I can reproduce the problem by having approx. 100 desktop icons), the same call produces a totally different display:
In this case, the Desktop items aren't shown anymore. I'm only allowed to explore my home folder and since I've lost the "My Computer" icon I cannot select a file/folder outside of this directory.
I'm searching what I'm missing here. Is there a limit in the number of subitems a root item can have for a correct display? Having a lot of desktop icons is certainely not a good practice, but as far as I know that shouldn't prevent this dialog to operate normally. I'm not sure if there is something wrong in the Delphi wrapper, or if that's a limitation of the API I didn't see on MSDN...
Any hint appreciated!
Yes, I can reproduce this behaviour. It's clearly a Windows limitation and the API in question does not offer you any way to increase buffers. I think your chances of working around it using SHBrowseForFolder are close to zero. Because SHBrowseForFolder is now a a legacy API.
If you are browsing for folders then you should use IFileOpenDialog in folder selection mode. That's a a much nicer dialog that uses the new Vista dialogs. In Delphi that is wrapped by TFileOpenDialog. Only use that if Win32MajorVersion>=6 though! For XP you need to call back on SHBrowseForFolder.
if Win32MajorVersion>=6 then
begin
FileOpenDialog1.Title := 'Sélectionnez un élément à ajouter :';
FileOpenDialog1.Options := FileOpenDialog1.Options + [fdoPickFolders];
if FileOpenDialog1.Execute then
Beep;
end else
begin
// revert to SelectDirectory
end;
The workaround I came to is to use the "old" (Win XP) UI, which can be done by not specifying the [sdNewUI] flag. In this case, all the items are correctly displayed.
That seems to be the only valid solution when the user must select files OR folders, something TFileOpenDialog is not capable of.
Related
Is it possible to use Acrobat.MenuItemExecute('Copy'); command with
AVDoc.OpenInWindowEx(FFilename, Panel1.handle, 0, True, 0,0, 2, 0, 0, 0);
in Delphi 7 and Acrobat XI Pro?
If you help me with an example I'll be glad.
I think the answer to this is probably "no" because before calling Acrobat.MenuItemExecute('Copy'), it is necessary to call BringToFront on the window containing the text you want to copy, otherwise the call to MenuItemExecute('Copy') will fail, even when the document is hosted in one of Acrobat's own windows. I don't see how you could do that successfully when the document window is hosted in your app, rather than Acrobat.
However, there are a few things you could add to your q that might assist in getting a better answer. [...]
Update Please disregard my comments in an earlier version of this answer saying that I could not reproduce the behaviour that I could not select text in the window opened using OpenInWindowEx. In fact, I can now select text fine, what I had overlooked previously is that I had set the Enabled property of my TPanel to False.
Unfortunately, I have still not been able to successfully call Acrobat.MenuItemExecute('Copy') and I am beginning to think that there is no way to do this in a hosted window. I have not found a definitive list, but various comments by Adobe staffers that google found make it clear that many MenuItemExecute strings just to not work when using OpenInWindowEx.
However that may not be the only way to retrieve the selected text back into the Delphi app.
If you look at the hosted window using a tool like WinSpy or Window Detective you will see that contained within the panel window is a whole host of Acrobat windows, including an AVL_AVView one with the Window text "AVPageView" which I imagine is the actual window displaying the PDF text.
I think the key to a possible solution is your observation, which I've confirmed, that pressing Ctrl-C in the window copies the text to the clipboard. So far I have not been able to achieve the equivalent in code, using techniques like keybd_event calls, various Delphi "SendKeys" routines and sending a WM_COPY message to the AVPageView window. I'm sure it must be possible, but I haven't yet found a way.
I'm showing where a file has been saved by using 'Showmessage' (in Win 7).
When the file path is long it gets truncated and elipsis get inserted.
eg
the path
C:\Users\Admin\Documents\SubFolderOne\AnotherSubFolder\MyFile.csv
gets displayed as
C:\Users\Admin\Documents\SubFolderOne\Ano...\MyFile.csv
Is there a way to make the message box wider and show all of the filename and path?
I have read this
http://zarko-gajic.iz.hr/displaying-long-non-breakable-text-file-path-in-messagedlg-truncationellipsis-issues/
which explains some of the reasoning and gives a rather unsatisfactory method for a TTaskDialog and I also I realise I could make my own form to act in the same way as Showmessage but I am wondering if there is a simpler solution using just Showmessage.
Is a simpler solution using just ShowMessage?
No there is not.
I can think of three obvious approaches, although doubtless there are more.
Create your own dialog
There's nothing particularly magical about a dialog. You can perfectly well create them yourself, and so have complete control over their appearance. The downside of course is that it can be hard to match the native platform appearance. Especially when you consider all the different Windows versions that you are typically expected to support.
Use CreateMessageDialog and customise this Delphi form
You can call the RTL function CreateMessageDialog to obtain a Delphi form that can be used to display your message dialog. You then have the opportunity to customize this dialog in any way you please.
Use the task dialog API
The task dialog API, introduced in Vista, affords control of the dialog width. Call TaskDialogIndirect, and specify a non-zero value for cxWidth.
Before ShowMessage put:
UseLatestCommonDialogs:= false;
I use Delphi 10.2 and it works.
I'm forking a existing Delphi 7 application to a new name. I used "Save Project as" to create the new project. I also changed the COM automation typelib library and interface names and GUIDs. All this worked fine.
But after I changed the Application.Title (>Project>Options>Application Settings>Title) the application is showing a strange behavior: It runs normally, but the wait cursor keeps rolling after the application starts. Every thing else seems to work fine.
If I change the title to any other name, the problem goes away. Even adding an space in the end of the name solves the problem. The name is 6 characters long, all letters. No symbols, spaces or numbers. I'm puzzled.
What is the Application.Title used for, besides showing in the Windows footer and task manager ?
Application title used solely to display the title for the application in the windows taskbar. By default it has same text as the name of EXE file. You can change it dynamically like this
Application.Title := 'two';
I confirmed it with the book "Delphi-7 second edition" writen by Homonenko Anatoly Dmitrievich. Even though it was written in Russian.
PS If you give me the word you used, I check it on my installation of Delphi-7 on Win-7x64
I have created a Delphi Service which prints TQuickReports. Everything works fine if compiled and run as a Windows Application. But when converted to operate as a service trying to create a form containing a TQuickRep component throws the exception.
This service runs fine on many other boxes but not this one in particular. Here are some details:
Using QuickReport version 4.07
Box is a Windows Server 2008 operating system.
Using Delphi 2007
Printer.Printers.Count is returning a positive value. In fact I can list out all of the printers.
I have tried running the service both using Local System Account and Logged on as an Admin.
Is there a default printer set up in session 0? Remember that under Vista / Server 2008 / Windows 7, services run in a separate session. Whether or not the logged-in user has a default printer set is not relevant - it's a per-session setting and doesn't affect session 0.
Can you rewrite the code to gracefully handle that exception and pick a printer to use?
You can solve this problem by creating a new dword UserSelectedDefault with the value: 1 in
HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows\SessionDefaultDevices\Session_ID
Make sure you have a local printer selected.
You might give the user a way to select the printer for the service. The Windows service probably does not have a default printer set.
Set TQuickRep.PrinterSettings.PrinterIndex to set the printer number. Then, TQuickRep.Print to print the report.
A colleague ended up finding the solution. I should have added these are "network" printers and not Local printers (at the time I didn't think this was related to the problem). So the service needed to be installed with "NetworkService" as the user account under the logon tab. From the Windows Help:
To specify that the service uses the Network Service account, click This account, and
then type NT AUTHORITY\NetworkService
We had a simular problem here. Using TS servers, Citrix and Powerfuse 9.
Powerfuse had all printers capitalized, however they were shared in a mixed case.
This combination caused Delphi/QReport to crash
When all printers are from printserver to powerfuse in the same case (not important upper or lower or even mixed), the problem was gone
Actually it is a Delphi(5) problem. The comparison of the available printers and the default printer is case sensitive (Printers.pas):
if TPrinterDevice(Objects[I]).Device = Device then
begin
with TPrinterDevice(Objects[I]) do
SetPrinter(PChar(Device), PChar(Driver), PChar(Port), 0);
Exit;
end;
Changing the comparison to:
if lowercase(TPrinterDevice(Objects[I]).Device) = lowercase(Device)
solves the problem.
If using terminal services 2008, same user for multiple sessions, you should look into the:
HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows\SessionDefaultDevices\Session_ID
instead of
HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows\
I solved a similar problem: If a Delphi application (or service) uses QuickReport, it runs before the system loads the default printer (or printers).
When QuickReport executes TQRPrinter.Init, the printer.printers.count is zero,
shortly after the system loads, the printer.printers.count is the number of printers,
but tqrprinter.int has already executed, so TQRPrinter.FPrinterOK is false,
you then see this error when you try open a QuickReport.
The solution for me was wait until the printers were loaded before launching the application (in citrix and terminal server). I solved this in two ways, either by overwriting tqrprinter or delay the dpr.
I put a TLinkLabel on my form, filled it in with a caption including a valid HTML link, and got some nice blue underlined text. When I ran the program, I expected it to invoke Firefox (my default browser) and open the link automatically. Apparently that's not the case.
The helpfile says I have to code this in an OnLinkClick event handler. It doesn't say anything about how to do that, though. It'll pass in a string value called "Link". How do I say "invoke the default browser and have it open Link"?
You can call ShellExecute.
I wrote this method for generic calls, and should works in your case.
procedure ShellOpen(const Url: string; const Params: string = '');
begin
ShellAPI.ShellExecute(0, 'Open', PChar(Url), PChar(Params), nil, SW_SHOWNORMAL);
end;
In your code you should call this
procedure TForm1.LinkLabelClick(Sender: TObject);
begin
ShellOpen(LinkLabel.Caption);
end;
I have all sorts of problems with TLinkLabel that ships with delphi 2010.
a) The control does not render as a hyperlink but as a simple label text on the form. b) the cursor does not change to point out this is a link even though I set the Cursor property. c) the OnLinkClick event does not fire at all.
I am working on windows 7.
So, as far as I am concerned, TLinkLabel does nothing as it should and is useless. ShellExecute is the only solution and must be placed in the OnClick event.
TLinkLabel provides a label that looks like a link. It's your job as the programmer to make it act like a link because only you can know what links are supposed to act like in your program. You wanted the label to automatically open the user's default Web browser using the URL in the label, but that's not the only thing links do. For example:
Internet Explorer is not my default browser, but when I click a link in Internet Explorer, I do not expect the linked page to open in Firefox.
When I click a link in the help program, I expect the linked topic to appear in the help program, not in any Web browser at all.
The preference pages in Eclipse are very complicated. Settings on one page are sometimes related to settings on another page. There are links on those pages that take the user directly to the related page. There is no URL and no HTML involved in this case, and yet they're still labels with underlined text.
Some programs try to offer a choice between opening links in new windows versus re-using old windows. You can't implement that feature without knowing which browser is in use. Your program might offer the user a choice to ignore the default browser setting and always use a specific one. To do that, your UI control can't make too many assumptions about what the program is supposed to do.
I'm guessing you're referring to a TLinkLabel control that comes with Delphi. (My versions don't have such a component.) I imagine that the Delphi control is meant to mimic the one in the .Net class library. It can hold multiple links, and each link can do something different.
If you want a control that always does the shell's default action for URLs, then consider using a different TLinkLabel; the one by Alexander Bach does exactly what you expected. It's from Delphi 3, but it should work unmodified in all later versions as well, including Delphi 2009. If you look at the code, you'll see how it works. It simply calls ShellExecute, as Cesar's answer demonstrates.
LOL, it's funny. So instead of setting crHandPoint as cursor, colored and underlined font and filling the OnClick event to standard TLabel we have component that knows link tag and which at all I need to supply with same On(Link)Click event :))
Only thing it is good for is that it makes easier to embed link into some text and that it is using system style of link...
p.s.: really you have to put Some text with link into the Caption and setup OnLinkClick to that ShellExecute...
I use a control called TInternetLabel instead. It does exactly what you want: on click it opens the browser so you don't have to put code in the OnClick event.
I tried this solution but it still gave problems in Delphi XE4, probably becasue ShellOpen does not understand the HTML-code in the Caption.
What worked for me was a combination of Cesar Romero (the basic code), Adam Feistner (The HTML-code in the Caption) and an older solution:
Put the URL in the HINT field.
Change the line: ShellOpen(LinkLabel.Caption);
to
ShellOpen(LinkLabel.Hint);
This worked for me.