WPF Live-Regions just for Narrator? - c#

I have a textblock (ContentTextBlock) with AutomationProperties.LiveSettings="Assertive". I'm just testing and checking how useful this feature is. And... am disappointed so far.
private void Button_Click(object sender, RoutedEventArgs e)
{
ContentTextBlock.Text += " test";
var peer = UIElementAutomationPeer.FromElement(ContentTextBlock);
if(peer == null)
{
peer = UIElementAutomationPeer.CreatePeerForElement(ContentTextBlock);
peer.RaiseAutomationEvent(AutomationEvents.LiveRegionChanged);
}
peer.RaiseAutomationEvent(AutomationEvents.LiveRegionChanged);
}
When using Narrator, this works as advertised. Whenever clicking the button, Narrator announces the TextBlock text ("test" "test test" "test test test")... But when I use NVDA or JAWS, nothing happens, although the screenreader versions are relatively up-to-date. Did they really not add any support for live-regions or am I just missing an important point?

Whilst I didn't manage to get live regions to work, I found another workaround:
Tolk by Davy Kager
Tolk is a library which can, among oterrs
Detect which supported screen reader, if any, is running
Pass strings to the screen reader's speech engine and braille.
Also has support for SAPI
To include Tolk in your C# project, download it from the link above, then include tolk.cs (from src/dotnet) in your project, and place tolk.dll (it's found in bin) in the folder with your executable (or somewhere in the PATH variable). Make sure that the dll version matches your CPU target (x86/x64). Do the same for the dlls in the lib directory. Then you can use it according to the code found in the examples folder.
PS. Tolk works on Win 7 as well, so that's a bonus. The live-regions of WPF were only supported from Win 8 on.

Related

c# customizing controls on a save dialog -- how to disable parent folder button?

I am working from the sample project here: http://www.codeproject.com/Articles/8086/Extending-the-save-file-dialog-class-in-NET
I have hidden the address/location bar at the top and made other modifications but I can't for the life of me manage to disable the button that lets you go up to the parent folder. Ist is in the ToolbarWindow32 class which is the problem. This is what I have at the moment but it is not working:
int parentFolderWindow = GetDlgItem(parent, 0x440);
//Doesn't work
//ShowWindow((IntPtr)parentFolderWindow, SW_HIDE);
//40961 gathered from Spy++ watching messages when clicking on the control
// doesn't work
//SendMessage(parentFolderWindow, TB_ENABLEBUTTON, 40961, 0);
// doesn't work
//SendMessage(parentFolderWindow, TB_SETSTATE, 40961, 0);
//Comes back as '{static}', am I working with the wrong control maybe?
GetClassName((IntPtr)parentFolderWindow, lpClassName, (int)nLength);
Alternatively, if they do use the parent folder button and go where I don't want them to, I'm able to look at the new directory they land in, is there a way I can force the navigation to go back?
Edit: Added screenshot
//Comes back as '{static}', am I working with the wrong control maybe?
You know you are using the wrong control, you expected to see "ToolbarWindow32" back. A very significant problem, a common one for Codeproject.com code, is that this code cannot work anymore as posted. Windows has changed too much since 2004. Vista was the first version since then that added a completely new set of shell dialogs, they are based on IFileDialog. Much improved over its predecessor, in particular customizing the dialog is a lot cleaner through the IFileDialogCustomize interface. Not actually what you want to do, and customizations do not include tinkering with the navigation bar.
The IFileDialogEvents interface delivers events, the one you are looking for is the OnFolderChanging event. Designed to stop the user from navigating away from the current folder, the thing you really want to do.
While this looks good on paper, I should caution you about actually trying to use these interfaces. A common problem with anything related to the Windows shell is that they only made it easy to use from C++. The COM interfaces are the "unfriendly" kind, interfaces based on IUnknown without a type library you can use the easily add a reference to your C# or VB.NET project. Microsoft published the "Vista bridge" to make these interfaces usable from C# as well, it looks like this. Yes, yuck. Double yuck when you discover you have to do this twice, this only works on later Windows versions and there's a strong hint that you are trying to do this on XP (judging from the control ID you found).
This is simply not something you want to have to support. Since the alternative is so simple, use the supported .NET FileOk event instead. A Winforms example:
private void SaveButton_Click(object sender, EventArgs e) {
string requiredDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
using (var dlg = new SaveFileDialog()) {
dlg.InitialDirectory = requiredDir;
dlg.FileOk += (s, cea) => {
string selectedDir = System.IO.Path.GetDirectoryName(dlg.FileName);
if (string.Compare(requiredDir, selectedDir, StringComparison.OrdinalIgnoreCase) != 0) {
string msg = string.Format("Sorry, you cannot save to this directory.\r\nPlease select '{0}' instead", requiredDir);
MessageBox.Show(msg, "Invalid folder selection");
cea.Cancel = true;
}
};
if (dlg.ShowDialog() == DialogResult.OK) {
// etc...
}
}
}
I don't this is going to work. Even if you disable the button they can type ..\ and click save and it will take them up one level. You can't exactly disable the file name text box and maintain the functionality of the dialog.
You'd be better off either using the FolderBrowserDialog and setting it's RootFolder property and asking the user to type the filename in or auto generating it.
If the folder you are wanting to restrict the users to isn't an Environment.SpecialFolder Then you'll need to do some work to make the call to SHBrowseForFolder Manually using ILCreateFromPath to get a PIDLIST_ABSOLUTE for your path to pass to the BROWSEINFO.pidlRoot
You can reflect FolderBrowserDialog.RunDialog to see how to make that call.
Since you want such custom behaviors instead of developing low level code (that is likely yo break in the next versions of windows) you can try to develop your file picker form.
Basically it is a simple treeview + list view. Microsoft has a walk-through .
It will take you half a day but once you have your custom form you can define all behaviors you need without tricks and limits.

Get selected text from another app into own C# app

I've a C# app that responds correctly to a global hotkey. I want to get the selected text from another app which has the focus if the global hotkey is pressed.
I tested native Win32 Api, then SendKeys (CTRL + C, Clipboard,...) and now Microsoft UI Automation! The problem is, this only works in Notepad, but not in Internet Explorer or Word or other apps.
I think there must be a better solution than the code I have. I read that sending CTRL + C should work fine, but that only works in Notepad too.
Here's the method I call when the global hotkey is fired:
public String GetSelectedTextFromApp()
{
String output = "";
AutomationElement focused = AutomationElement.FocusedElement;
object pattern;
TextPatternRange[] trs;
if (focused.TryGetCurrentPattern(TextPattern.Pattern, out pattern))
{
TextPattern tp = (TextPattern)pattern;
trs = tp.GetSelection();
output = trs[0].GetText(-1);
}
return output;
}
The control you're trying to automate might not be implementing TextPattern. It might only implement ValuePattern. Also, it's possible that the control you're focused on isn't the control which actually contains the text, but rather a wrapping control under which you'll find an AutomationElement implementing the above mentioned patterns. Another possibility is, like Andrii said, is that the control doesn't support UIA at all (though I find it hard to believe in case of MS Word).
In such cases, it's worth working with UISpy.exe which will help you see the visual tree of the application you're trying to automate. You'll also be able to see the supported Patterns for each AutomationElement. You can also call GetSupportedPatterns() on every AutomationElement, to see which Patterns are currently supported.

Cannot add icon in shell extension with C#

I've found a very nice tutorial and i am trying to understand something that is not in this tutorial (because the tut itself works fine)
http://www.codeproject.com/Articles/9163/File-Rating-a-practical-example-of-shell-extension
When you look at applications like WinRar, TortoiseSVN, Antivirus-apps and many more, there is an icon next to the Shell Extension Item.
I would like to know how this is done. (Programmatically with C#)
Adding a separator works, adding a submenu works and click+action also works, but i'm struggling with the icon. This cannot be so hard. Can somebody help me?
And please don't say that Microsoft doesn't longer support this in .NET 4.0, because it is not guaranteed and therefore they don't supply samplecode. If all those other apps can do it, then it is possible.
Please supply me some sample code, some tutorials or maybe even a working piece of code.
Please have a look at the following article, it uses .NET 4.0 it to create Windows Shell Extensions using the SharpShell nuget package.
NET Shell Extensions - Shell Context Menus
Using this library, you can set the image directly while creating the contextmenustrip as shown below
protected override ContextMenuStrip CreateMenu()
{
// Create the menu strip.
var menu = new ContextMenuStrip();
// Create a 'count lines' item.
var itemCountLines = new ToolStripMenuItem
{
Text = "Count Lines...",
Image = Properties.Resources.CountLines
};
// When we click, we'll count the lines.
itemCountLines.Click += (sender, args) => CountLines();
// Add the item to the context menu.
menu.Items.Add(itemCountLines);
// Return the menu.
return menu;
}
You only have to add to the following registry key: HKEY_LOCAL_MACHINE\SOFTWARE\Classes*\shellex\ContextMenuHandlers
and here is the code:
string TimeStamp = DateTime.Now.ToString("dd-MM-yyyy");
string key = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\*\\shellex\\ContextMenuHandlers\\Winrar";
string valueName = "MyWinrar";
Microsoft.Win32.Registry.SetValue(key, valueName, HERE WHAT YOU WANT TO START, Microsoft.Win32.RegistryValueKind.String);
i hope it works for you!
All the apps you listed use COM and unmanaged code to create overlay icon handlers. There is even a special project TortoiseOverlays that provides a common library for drawing icons for TortoiceCSV, TortoiseSVN and TortoiseGIT. You can take a look at it's source code to find out how it is done. If you want to draw similar icons, you should probably just reuse it.
Using .Net for this type of extensions is not recommended, because when multiple extensions, built against different .Net versions would attempt to load in explorer process, they will crash the explorer.

I need a GUI for my project in c++

I need a GUI system that contain:
a tree list that each item of list linked to a view and when I click on a Item open the view
for next step
I want to insert to each view some grids.
I see a demo example named :dockpanelsuite http://sourceforge.net/projects/dockpanelsuite/
there is a explorer and multi document
I think that I can change it to my requirment.
but this is in C# and I need something in C++.
if is same sample in MFC ,or I can combine them?
what about performace and stability?
thanks herzl
use QT. It's comprehensive, has a lot of tutorials in the web out there, is portable and is in C++.
Qt is better than MFC for a number of reasons including:
. > 1.It is open source
2.It is cross platform. It works on Linux, some mobile devices and
Mac
OSX. This makes it easier to port
programs to other platforms.
> 3.Qt is much easier to use and learn that MFC.
> 4.Above all Qt is well documented.
MFC is too big library. Go for win32 if you only want simple GUI
Win32++ as also a nice little library for windows only development.
You could start creating a new MFC SDI App in the App Wizard pick the Visual Studio Project Style, you will need to use the Document/View architecture.
With the generated App you could work you way to have in the left docking pane a derived ListControl class from CMFCListCtrl.
class CMyListCtrl : public CMFCListCtrl
{
// Your stuff goes here....
public:
DECLARE_MESSAGE_MAP()
afx_msg void OnLvnItemchanged(NMHDR *pNMHDR, LRESULT *pResult);
}
in the implementation file you could handle the click event with something like this..
BEGIN_MESSAGE_MAP(CMyListCtrl, CMFCListCtrl)
ON_NOTIFY_REFLECT(LVN_ITEMCHANGED, &CMyListCtrl::OnLvnItemchanged)
END_MESSAGE_MAP()
void CMyListCtrl::OnLvnItemchanged(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
POSITION p = GetFirstSelectedItemPosition();
int nSelected = GetNextSelectedItem(p);
if (nSelected != -1)
{
CString strText = GetItemText(nSelected, 0);
// we open the document.....
CMainFrame *pFrame = static_cast<CMainFrame *> (AfxGetMainWnd());
CWinApp *app = AfxGetApp();
app->OpenDocumentFile(strText,FALSE);
pFrame->ShowJobsProperties ();
}
*pResult = 0;
}

Drag & drop of a dynamically created shortcut

I have a C# application that creates shortcuts to launch other programs with specific arguments and initial directories. I would like the user to be able to drag a shortcut from the Windows form and drop it anywhere relevant like the desktop, the start menu, and so on but I don't really know how to handle that, could anyone point me in the right direction?
I have seen a few samples using PInvoke and IShellLink like this one, or read answers on SO like here, which already help create shortcuts and save them in a .lnk file. I assume I have to hand over data in a DoDragDrop() call when the user initiates a drag operation, for example by handling a MouseDown signal. That's as far as I got, I suppose I need to know exactly which type the target is expecting to accept the drop, and how to serialize the shortcut, but couldn't find any information on that part.
Perhaps another option would be to get the location of the drop, and manage that from my application, but there again I'm a bit clueless as how to do that.
The framework version is currently 3.5, and I'm only considering Windows platforms.
Thanks in advance for your help!
Update/Solution:
Using the ShellLink code mentioned above to create a temporary shortcut file, I simply used DataObject for the drag and drop, like in the following example:
private void picShortcut_MouseDown(object sender, MouseEventArgs e)
{
ShellLink link = new ShellLink();
// Creates the shortcut:
link.Target = txtTarget.Text;
link.Arguments = txtArguments.Text;
link.Description = txtDescription.Text;
link.IconPath = txtIconFile.Text;
link.IconIndex = (txtIconIndex.Text.Length > 0 ?
System.Int32.Parse(txtIconIndex.Text) : 0);
link.Save("tmp.lnk");
// Starts the drag-and-drop operation:
DataObject shortcut = new DataObject();
StringCollection files = new StringCollection();
files.Add(Path.GetFullPath("tmp.lnk"));
shortcut.SetFileDropList(files);
picShortcut.DoDragDrop(shortcut, DragDropEffects.Copy);
}
Quite complicated if you consider the PInvoke code (not shown here), and I still need to create this temporary file with the target name. If anyone knows a... erm, shortcut, it's welcome! Perhaps by porting the code for which John Knoeller gave a link (thanks!).
Raymond Chen did a whole article on this very topic on his blog check out dragging a virtual file
I answered a question sort of similar to this on a previous thread. This might be a starting point for you.
Drag and Drop link

Categories

Resources