I am writing a Crystal Report viewer in C# Visual Studio. One thing that I have noticed is users want to use Ctrl+C to copy the text they selected (not using the copy button on the viewer). They said it was a feature in a third party application that we switched over from.
How would I achieve this?
I have set the form KeyPreview to true. Using Ctrl+C still does not copy the selected text.
Looping through all of the CrystalReportViewer objects Controls, I have been able to find the control that was highlighted using the Control.Focused getter but there is no indication on which section of that Control contains the highlighted text. That means I cannot even manually copy the text to the clipboard.
I have also tried using the SendMessage PInvoke with WM_COPY, no success.
Here is the code I am using to step through the viewer looking for the correct data and the PInvoke message I am sending.
[DllImport("USER32.DLL", EntryPoint = "SendMessage")]
public static extern IntPtr SendMessage(int hWnd, int Msg, int wParam, IntPtr lParam);
public const int WM_COPY = 0x0301;
CrystalReportViewer viewer;
public void CopySelection()
{
Control.ControlCollection c = viewer.Controls;
GetControl(viewer.Controls);
IntPtr p = SendMessage((int)viewer.Handle, WM_COPY, (int)IntPtr.Zero, IntPtr.Zero);
Console.WriteLine("Copied! " + p);
}
private void GetControl(Control.ControlCollection cItem)
{
foreach (Control c in cItem)
{
if (c.Focused)
Console.WriteLine(c.Focused);
if (c.Controls.Count > 0)
GetControl(c.Controls);
string txt = c.Text;
}
}
Does anybody have any ideas?
Edit:
It seems that after using the 'Find Text' button from the viewer, you are able to copy any text throughout the report with Ctrl+C. Kind of strange. On another note, is there a way to programmatically run the 'Find Text' option?
Related
I'm a little stuck. I have successfully changed the text in normal TextBoxes in said application but am stuck on changing this one. Im not sure what this is called so I have called it a scroll TextBox, also it will only accept numbers not letters.
The code im using
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, int lParam);
const int WM_SETTEXT = 0X000C;
public void Main(IntPtr handle, string text)
{
SendMessage(handle, WM_SETTEXT, 0, 555);
}
I have also tried changing lParam into a StringBuilder which has worked in other TextBoxes but hasnt for this one.
This is the type of TextBox.
Using windows defender there isn't a Edit child like the usual TextBoxes. The only handle I have is for the whole element.
What are my choices here to be able to get that text changed?
The control is known as a NumericUpDown. The text is a representation of the numerical value that it holds, unlike a traditional textbox where you may parse the text to get a number. Depending on your intentions, you may need to find a way to change the underlying numerical value to effectively modify this type of control from another process.
I'm making a dialog that look like Notepad's Find Dialog. I notice that the underline character of Notepad's Find dialog always show all the time (I have to press ALT key to see this with my dialog). How to always show underline character like that?
I try to use SendKeys.Send("%") on Form_Load event but nothing happens.
There is another problem, when I press ALT key on child Form, it show underline charater of parent Form too. How to avoid that?
This is sreenshot of Notepad's find dialog:
I pretty sure this is not about Ease of Acess Center, because the main Form of Notepad doesn't always show this.
Seeing the n in "Find" underlined in the Notepad dialog is an intentional bug. The dialog isn't actually part of Notepad, it built into Windows. Underlying winapi call is FindText(). The feature is in general a pile 'o bugs, one core problem is that creating a new window after the UI is put in the "show underlines" state doesn't work correctly, that new window isn't also in that state. Presumably the intentional bug was based on the assumption that the user would be somewhat likely to use the Alt key to get the dialog displayed. Yuck if he pressed Ctrl+F.
The Windows dialog probably does it by simply drawing the "Find" string with DrawText() with the DT_NOPREFIX option omitted. You could do the same with TextRenderer.DrawText(), omit the TextFormatFlags.HidePrefix option.
Not exactly WinFormsy, you'd favor a Label control instead of code. It is hackable, you'd have to intentionally send the message that puts the UI in the "show underlines" state for your own dialog. Do so in an override for the OnHandleCreated() method:
protected override void OnHandleCreated(EventArgs e) {
const int WM_UPDATEUISTATE = 0x0128;
base.OnHandleCreated(e);
SendMessage(this.label1.Handle, WM_UPDATEUISTATE, new IntPtr(0x30002), IntPtr.Zero);
}
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
Where "label1" is the control you want to show underlines. Repeat for other controls, if any. It is supposed to work by sending the message to the form, that this doesn't work is part of the pile 'o bugs. Yuck.
Fwiw: do not fix this by changing the system option as recommended in the duplicate. That's very unreasonable.
You can use RichTextBox control and extension method for that:
public static class FontHelper
{
public static void Underline(this RichTextBox txtBox, int underlineStart, int length)
{
if (underlineStart > 0)
{
txtBox.SelectionStart = underlineStart;
txtBox.SelectionLength = length;
txtBox.SelectionFont = new Font(txtBox.SelectionFont, FontStyle.Underline);
txtBox.SelectionLength = 0;
}
}
}
richTextBox1.Text = "Search for";
richTextBox1.Underline(7, 1); // index and length of underlying text
I need to restore ("un-minimize") a WPF window that has already been created but the window that's currently on top (not necessarily WPF) can't lose focus or activation. I have tried using all WIN32 functions I can find, to no avail. Getting really frustrated by now, would really appreciate any pointers and tips.
Obviously just changing to WindowState.Normal in WPF doesn't cut it as this makes the window receive focus and activation as-well. I have also tried all sorts of combinations with setting Hidden and IsEnabled while restoring.
I have tried WIN32 SetWindowPos with HWND_TOP, HWND_TOPMOST etc. but this function is not intended to restore windows and will only change position of already "displayed" windows.
Tried WIN32 ShowWindow and SetWindowPlacement but no luck there either. Tried a desperate attempt at adding a HwndHook to try and listen for WM_SETFOCUS and restoring focus to the original window but i only get zero for the last focused window handle..
Edit - Solution with window extension after tip from Joel Lucsy:
public static class RestoreWindowNoActivateExtension
{
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, UInt32 nCmdShow);
private const int SW_SHOWNOACTIVATE = 4;
public static void RestoreNoActivate(this Window win)
{
WindowInteropHelper winHelper = new WindowInteropHelper(win);
ShowWindow(winHelper.Handle, SW_SHOWNOACTIVATE);
}
}
Call ShowWindow passing the SW_SHOWNOACTIVATE flag.
I'm trying to initiate the drop down list click for a combobox of type MultiColumnComboBox (RadMultiColumnComboBox).
The behavior I'm trying to emulate is when the user clicks the [v] button of the drop down, which shows the actual list.
My control is a Telerik.WinControls.UI.RadMultiColumnComboBox.
I saw a post on the Telerik forums suggesting to do something like this:
Dim item As RadTextBoxItem = TryCast(Me.radMultiColumnComboBox1.MultiColumnComboBoxElement.Children(2).Children(0).Children(0), RadTextBoxItem)
If item IsNot Nothing Then
AddHandler item.Click, AddressOf OnTextBoxItem_Click
End If
Seems like a viable solution, but I'm not sure how this would work on my C# control.
There is also a Win32 hack I found, but this would not pass code review:
// Declare the following in your class
[DllImport("user32.dll")]
public static extern int SendMessage(int hWnd, int msg, int wParam, IntPtr lParam);
public const int CB_SHOWDROPDOWN = 0x14F;
// In the leave event of combobox, use the following code:
SendMessage(comboBox1.Handle.ToInt32(), CB_SHOWDROPDOWN, 1, IntPtr.Zero);
If anyone is familiar with a WinForms ComboBox and can help me figure out how to kick off the Show Items/Elements/List event (or whatever its called), I'd really appreciate it!
The equivalent c# is:
RadTextBoxItem item = this.radMultiColumnComboBox1.MultiColumnComboBoxElement.Children(2).Children(0).Children(0) as RadTextBoxItem;
if (item != null) {
item.Click += OnTextBoxItem_Click;
}
Check if it works for you.
If I understand correctly, you want to open the drop down programatically. If this is the case, here is how you can do that:
radMultiColumnComboBox1.MultiColumnComboBoxElement.ShowPopup();
I am populating a WinForms TreeView control and setting the font attributes of each node differently as they are loaded.
The nodes also allow inline editing (changing the text by pressing F2, or clicking once selected like folder names in Windows Explorer).
When the node goes into edit mode though, the font used when editing reverts to the default font of the TreeView control, not that specific node's font.
Is it possible to set the font of the edit control used when editing each node, to match the font used for displaying that TreeView node? (If so, how?)
As you said, an examination of the TreeNode source reveals that the node is using an Edit Control (from Windows UI Controls, not .NET Forms) when it goes into edit mode. I don't see anything in the class that will set the font in edit mode, so I think you will need to post messages directly to the Edit Control. Use TVM_GETEDITCONTROL to get a handle to it, and WM_SETFONT to set the font. You will probably want Font.ToHfont(), as well.
Edit: here's an example of how you can invoke SendMessage to accomplish the font change.
[DllImport("user32.dll")]
internal static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
internal const int WM_SETFONT = 0x0030;
internal const int TVM_GETEDITCONTROL = 0x110F;
private void treeView1_BeforeLabelEdit(object sender, NodeLabelEditEventArgs e)
{
TreeNode nodeEditing = e.Node;
IntPtr editControlHandle = SendMessage(treeView1.Handle, (uint)TVM_GETEDITCONTROL, IntPtr.Zero, IntPtr.Zero);
if (editControlHandle != IntPtr.Zero)
{
SendMessage(editControlHandle, (uint)WM_SETFONT, nodeEditing.NodeFont.ToHfont(), New IntPtr(1));
}
}