There is a desktop window, which has more tabs, and some tabs include a text editor.
The editor buttons have the following mapping on the first tab (simplified here):
Window.PageControl.Tab1.Editor.Panel.Button1
Window.PageControl.Tab1.Editor.Panel.Button2 and so on.
The editor buttons have the following mapping on the second tab (simplified here):
Window.PageControl.Tab2.Editor.Panel.Button1
Window.PageControl.Tab2.Editor.Panel.Button2 and so on.
(Sometimes the Editor and other objects between Editor and Panel are cached and their mapping is not stable.)
I wrote a test which checks the functions of the text editor in the following way:
Window.PageControl.TabIndex := 1;
editor_test;
Window.PageControl.TabIndex := 2;
editor_test;
The editor_test looks like:
Window.PageControl.Refresh;
lprops := ['FullName','WndClass'];
lvals := ['*Panel', 'TWPToolPanel'];
ltarget := Aliases.(application name).Find(lprops,lvals,20,true);
ltarget.Button1.Click;
ltarget.Button2.Click...
editor_test properly works on any single tab of the window. Although, when I try to run the editor_test more times in one test, the test fails after changing tab, because it searches the buttons on the previous tab.
I tried Refresh and RefreshMappingInfo methods on the common parent object of the tabs (see above), but they doesn't help.
(The names and number of tabs can change in the window depending on the conditions.)
Is there any other way to clear cached mapping tree during test run? Is there any mistake in the concept?
Thank you in advance for any suggestion!
The solution was to complement the editor test in the following way:
lprops := ['FullName','WndClass', 'VisibleOnScreen'];
lvals := ['*Panel', 'TWPToolPanel', true];
Using this, TestComplete does not recognize editor buttons on inactive tabs of the window, which happened in the original scenario.
Related
I want to know if there's a way to insert, for example, a FilePath in a DialogBox opened by Windows itself, but inserted from a Delphi variable to the Windows Dialog? Something like, click on an Upload button in any website that does open the File Explorer Dialog, and in Delphi send the value of the Path to the File Explorer of Website.
PS : I already have the code to get his HWND handle.
I don't know if this is possible, or is there's a way to do it.
Edit : A Select File from the site, what I want is simply to input the FilePath of this site by an app variable in Delphi.
Variants
If you know that dialog window's handle already then there are at least 2 variants:
finding the control by going through the children hierarchy, using FindWindowEx()
relying on the dialog template's IDs, using GetDlgItem()
Both may work out great, but are at the same time fragile, since the dialog window's structure (as per its controls and IDs) can change even by Service Packs already, let alone entire Windows versions. My experience here is from Win2000 up to Win7 and on those systems it worked.
Dialog versions
What you posted as screenshot is the "Vista" version of the dialog; the older "Win95" version is identical in terms of accessing the "filename" ComboBox.
The old one is typical for having the buttons ("open" and "cancel") in one row. Older software might still use these, but your web browser most likely not:
The one since Vista has its buttons in one line and is notable of featuring a full folder pane:
But both pictures show that the control layout is the same: a ComboBoxEx32 is a direct child of the window, having its own child(s). So we can use the same code for both versions.
Code
var
hDialog, hCbx32, hCbx, hEdit, hFilename: HWND;
sText: String;
begin
hDialog:= 9568854; // Dialog window, class "32770"
sText:= 'M:\my\filename.ext'; // What should be set
// Variant #1: finding the control by parents and childs.
// Luckily both the old dialog up to XP and the new dialog
// since Vista do not differ as per the filename ComboBox.
hCbx32:= FindWindowEx( hDialog, 0, 'ComboBoxEx32', nil ); // Most likely the 3rd child control
hCbx:= FindWindowEx( hCbx32, 0, 'ComboBox', nil ); // Actual ComboBox inside that
hEdit:= FindWindowEx( hCbx, 0, 'Edit', nil ); // Edit control inside ComboBox
SendMessage( hEdit, WM_SETTEXT, 0, LPARAM(PChar(sText)) );
// Variant #2: using dialog template IDs, which haven't
// changed since XP with one of its Service Packs. However,
// tested with Win7 only.
hFilename:= GetDlgItem( hDialog, $47C ); // "cmb13", found at least in XP SP3
if hFilename= 0 then hFilename:= GetDlgItem( hDialog, $480 ); // "edt1" = Maybe prior to XP without any SP
SendMessage( hFilename, WM_SETTEXT, 0, LPARAM(PChar(sText)) );
end;
One of both variants should do already. Successfully tested on Win7x64
using Paint's "Open" command for the Vista dialog version, and
one of my older program's "Open" command for the Win95 dialog version:
the text in the filename's ComboBox was set as expected.
When you create a Delphi project and add a combobox and set ComboBox1.Items.Add('Zebra & Zulu') it shows "Zebra & Zulu" when you dropdown the list. Perfect.
When you create a Firemonkey project and add a comboxbox or comboedit and set ComboBox1.Items.Add('Zebra & Zulu') or ComboEdit1.Items.Add('Zebra & Zulu') it shows "Zebra Zulu" (no ampersand shows) when you dropdown the list. However, when you select it using the comboedit the text field part shows "Zebra & Zulu". Just weird.
Now there is a work around (sort of) but to me it is questionable. Add a second ampersand and the dropdown list shows the ampersand. However, adding the second ampersand shows up on the comboedit text field part. Bad.
My question is can you force these combo controls dropdown list to show the ampersand? And why is the ampersand missing in the first place?
This seems to be inbuilt behaviour that is likely leftover from the VCL's accelerator key handling. There does not seem to be a way to modify this behaviour with styles or options :
procedure TTextControl.DoChanged;
var
TextStr: string;
begin
if Assigned(FITextSettings) then
FITextSettings.TextSettings.BeginUpdate;
try
if Assigned(FITextSettings) then
FITextSettings.TextSettings.Assign(ResultingTextSettings);
TextStr := DelAmp(Text); // **! Here deleting ampersands unconditionally
if Assigned(FTextObject) then
begin
UpdateTextObject(FTextObject, TextStr);
// ... etc - method continues
One workaround is to use the unicode full-width ampersand :
ComboBox1.Items.Add('Zebra & Zulu');
Obviously not appealing for a number of reasons.
From the code above, this naturally affects all FMX TTextControls - even a TLabel, for example, will not display an ampersand when assigned :
Label1.Text := 'Zebra & Zulu';
Even in a VCL application, for interest, this:
Label1.Caption := 'Zebra & Zulu';
will render as
Zebra _Zulu
Although a VCL TComboBox will correctly render an item with a single ampersand...
This is an open QC, albeit one that does not appear in any hurry of being addressed :
http://qc.embarcadero.com/wc/qcmain.aspx?d=122564
This question already has answers here:
How to associate a program with a file type, but only for the current user?
(2 answers)
Closed 8 years ago.
How can i auto-open a custom extension in my Delphi app ? I'm trying to make application
that loads text files but with a different extension.
Example : Text.DZ | all i want is when i click the file with .DZ Extension it opens my app automatically and loads the text inside into the memo1.lines.text.
I know that i have to register my new custom extension but i have no idea how to do it and
load the text into my app.
Also if you can include a source-code example that would be awesome.
Any help will be much appreciated ! and
Sorry for my newbiness and bad English explanation but i hope you guys understand me (^-^)/.
There's a way to do it programmatically, although I don't recall how off the cuff.
That said, if you're just wanting to do it for your own personal use, not for a piece of software you'll be distributing to others, then the easiest way is to use Windows Explorer: click the data file you want, then right-click and select Open With -> ... you'll probably need to select the Other... option at the bottom. That will bring up a dialog box that lets you choose your app. There should also be a checkbox somewhere that says something like "Make Default" or "Always Open With This" or something along those lines. Make sure that box is checked. Then click OK a couple of times and you're off to the races.
But you'll also need to set up your app to read the filename from the command line. You use ParamStr and ParamCount for this.
for i := 0 to ParamCount do
ShowMessage('Parameter '+IntToStr(i)+' = '+ParamStr(i));
When you double-click on the data file, it will open your app and pass this filename as ParamStr(1). So when you get it, simply do something like this:
memo1.lines.LoadFromFile( ParamStr(1) );
Use this as a STARTING POINT (it won't compile if you just copy-and-paste!):
procedure TMyForm234:FormCreate( blah blah )
begin
if ParamCount > 0 then
theMemo.Lines.LoadFromFile( ParamStr(1) );
end;
I have tried many different libraries, but none came.
None of them can not be specified without introducing his own style in Painter.
I need to be able to quickly and dynamically change the style tab.
In response, I showed my developments.
If someone has similar developments - write them in response.
I decided to upgrade the simplest of them: TJvTabBar of JVCL (latest revision: 13415)
Here is the result.
Before (default)
After
Style sources (All graphics imported from png files with transparency)
Easy apply any personal style to any JvTabBar
var tmp:TStrings;
begin
tmp:=TStringList.Create;
tmp.Values['TOP_background']:= ExtractFileDir(Application.ExeName)+'\skins\default\tabs-TOP_background.png';
tmp.Values['TOP_active_left_side']:= ExtractFileDir(Application.ExeName)+'\skins\default\tabs-TOP_active_left_side.png';
tmp.Values['TOP_active_right_side']:= ExtractFileDir(Application.ExeName)+'\skins\default\tabs-TOP_active_right_side.png';
tmp.Values['TOP_active_center']:= ExtractFileDir(Application.ExeName)+'\skins\default\tabs-TOP_active_center.png';
tmp.Values['BOTTOM_background']:= ExtractFileDir(Application.ExeName)+'\skins\default\tabs-BOTTOM_background.png';
tmp.Values['BOTTOM_active_left_side']:= ExtractFileDir(Application.ExeName)+'\skins\default\tabs-BOTTOM_active_left_side.png';
tmp.Values['BOTTOM_active_right_side']:= ExtractFileDir(Application.ExeName)+'\skins\default\tabs-BOTTOM_active_right_side.png';
tmp.Values['BOTTOM_active_center']:= ExtractFileDir(Application.ExeName)+'\skins\default\tabs-BOTTOM_active_center.png';
tmp.Values['CLOSEBUTTON_normal']:= ExtractFileDir(Application.ExeName)+'\skins\default\tabs-CLOSEBUTTON_normal.png';
tmp.Values['CLOSEBUTTON_selected']:= ExtractFileDir(Application.ExeName)+'\skins\default\tabs-CLOSEBUTTON_selected.png';
tmp.Values['CLOSEBUTTON_disabled']:= ExtractFileDir(Application.ExeName)+'\skins\default\tabs-CLOSEBUTTON_disabled.png';
tmp.Values['CLOSEBUTTON_closing']:= ExtractFileDir(Application.ExeName)+'\skins\default\tabs-CLOSEBUTTON_closing.png';
tmp.Values['CLOSEBUTTON_modified']:= ExtractFileDir(Application.ExeName)+'\skins\default\tabs-CLOSEBUTTON_modified.png';
tmp.Values['CLOSEBUTTON_closing_modified']:= ExtractFileDir(Application.ExeName)+'\skins\default\tabs-CLOSEBUTTON_closing_modified.png';
JvTabBar1.StyleImages:=tmp;
tmp.Values['BOTTOM_background']:= ExtractFileDir(Application.ExeName)+'\skins\default\MYMOD_tabs-BOTTOM_background.png';
JvTabBar2.StyleImages:=tmp;
Main changes
Added ability to specify their own style ( JvTabBar1.StyleImages )
Added the ability to move the close button to the right ( JvTabBar1.CloseButtonRight: = true or false )
Many fixes to the size and position of text / icons / buttons / scroll
My JvTabBar.pas mod You can download it here http://pastebin.com/JmbufHy0
And example source style + JvTabBar.pas http://www.sendspace.com/file/shhuzr
I've been trying to use tomazy's FutureWindows infrastructure (see his answer at Delphi GUI Testing and Modal Forms or the home of the tool at https://github.com/tomazy/DelphiUtils), but would like to know if and how can it be used with standard Windows file open dialogs? They don't seem to be inheriting from TControl, which the FutureWindows infra seems to assume (unless I've misunderstood it).
What I'd like to do is basically to just select a file in an OpenFileDialog which is opened modally by a command within my testing, but haven't yet been able to figure out how to do this.
Use a tool like Spy++ to find out what the window class name is. For example, on my Windows 7 machine, the window class name for a system file open dialog is #32770 (Dialog).
My current solution is below:
TFutureWindows.Expect(MESSAGE_BOX_WINDOW_CLASS)
.ExecProc(
procedure (const AWindow: IWindow)
var
DlgHandle: HWND;
FileName: string;
begin
FileName := ExpandFileName('myFileToUse.txt');
DlgHandle := AWindow.GetHandle;
Windows.SetDlgItemText(DlgHandle, 1148, PChar(FileName));
end
)
.ExecSendKey(VK_RETURN);
So basically sending a message using Windows API. The ideas (and the ID 1148) were found from here: http://social.msdn.microsoft.com/forums/en-US/winforms/thread/62d5db14-5497-4ceb-8af0-d7f81732e937/
Possible better solutions are welcome, but this seems fine enough for me at least for now.
Thanks for the comments so far!