It's a small thing but I was just wondering...
Visual Studio 2008, C#.
I have a master-detail form with databound controls. When user selects the record in a listbox, all the details are updated in multiple databound controls on the form.
As it happens, they kind of 'flash', or blink, when repopulated with new data and it's sort of like an electrical wave going across the form in a fraction of second :) don't know how to explain it better
Not a big deal, but still, it looks "shaky" and ugly, so, for the sake of ellegance, I was just wondering whether there is some easy way to prevent it?
I thought about calling SuspendLayout and ResumeLayout (on the container control), but what events should I handle? listBox_SelectedValueChanged for suspending it, I guess ... but for resuming?
You could prevent the flicker by suspending painting when the control's data is refreshed.
From this stackoverflow question:
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);
private const int WM_SETREDRAW = 11;
public static void SuspendDrawing(Control parent)
{
SendMessage(parent.Handle, WM_SETREDRAW, false, 0);
}
public static void ResumeDrawing(Control parent)
{
SendMessage(parent.Handle, WM_SETREDRAW, true, 0);
parent.Refresh();
}
As far as which events to handle, I'm not sure.
I didn't notice that "SuspendLayout" did anything for me, but worth giving it a shot. I think you would want to latch onto the "CurrentChanged" event for when the selected item is changed wholesale.
Have you set the DoubleBuffered (under "behavior" in the props window) to true?
control.DoubleBuffered = true;
A bit 'o history: http://www.codeproject.com/KB/graphics/DoubleBuffering.aspx
Related
I'm looking for some guidance here, if not an example of how to accomplish what I am looking to do in C-Sharp(C#).
There is a particular button on a MS Access Ribbon that I would like to click. The MS Access window has a custom UI and custom buttons in different groups. When the button in the first group is clicked, it then opens a childform window. I need to automate that particular step and have my C# application programmatically open that child form by clicking the button or any other means to get it open.
I attempted to do this with the SendKeys and FindWindow functions, but this prove to be rather faulty, because the ALT id's kept changing in MS Access and the SendKeys would stop working.
I've tried searching for articles that would help me with this issue, but all I came across are tutorials on how to make a custom add-in for MS ribbon (I do not want this).
There might be a better way to do this and any help with it is greatly appreciated!
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string strClassName, int nptWindowName);
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
Public Void SendTest()
{
IntPtr WinHandle = FindWindow("OMain", 0); // OMain = Window Class --found window by class
if (WinHandle == IntPtr.Zero)
{
MessageBox.Show("Program is not running or could not be detected.");
return;
}
SetForegroundWindow(WinHandle);
SendKeys.SendWait("%"); // ALT
SendKeys.SendWait("Y1"); // Y1
SendKeys.SendWait("Y1"); //Y1
}
I am using the following to Show/Hide window by its handle:
[DllImport("user32.dll")] private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
// Win32 API Constants for ShowWindowAsync()
private const int SW_HIDE = 0;
private const int SW_SHOW = 5;
ShowWindowAsync(_hWnd, SW_SHOW); //Show Window
ShowWindowAsync(_hWnd, SW_HIDE); //Hide Window
When I hide Sticky Notes and then Show them again it cause visual "holes" in the stickies and I have to close the Sticky Notes and reopen.
Here's a screenshot of the problem:
I believe the problem is specific to the Sticky Notes.
I dont know why it happens but I would like to solve it somehow..
I thought about checking if the window is Sticky Notes, and if it is then Open/Close it instead of Show/Hide will act the same but I dont really like it - feels hacky.
Changing from ShowWindowAsync() to ShowWindow() solved the problem.
I dont know why the ShowWindowAsync() cause this problem and I wish for an educating answer here but for now, as long as my problem is solved I am happy.
I want to paste text from my text box or rich text box in C# windows form application to out side of the form for example:
//on a button click event
textbox1.text=Clipboard.SetText(); // this will set text to clipboard
now I want when I click in address bar of Firefox or Google chrome to get the same text as I typed in my windows form application, as I can do it by CTRL+V but I want a C# program to do so for me and get text from clipboard when ever I click in address bar or rename a folder.
You could just turn on some windows disability settings, If dragging or pasting is too awkward.
If you really want to implement this, you need a global hook on the mouse so you can recieve mouse events from outside your application. See here or perhaps here.
Then you have a problem, do you want to paste anywhere or just in address bars. First you'll have to define what an address bar window is and work out if that is what has the focus.
Its a lot of effort and the behaviour is not especially desirable. If you really want this, please expand your question and improve its readability so that this post will be useful to future visitors.
This is completely untested, and I've never used these DLL calls in C#, but hopefully it will do the trick or at least come close...
public class Win32
{
public const uint WM_SETTEXT = 0x000c;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
public static extern IntPtr SendMessage(HandleRef hWnd, uint Msg, IntPtr wParam, string lParam);
[DllImport("user32.dll")]
static extern IntPtr WindowFromPoint(int xPoint, int yPoint);
}
Elsewhere in the code...
IntPtr theHandle = WindowFromPoint(Cursor.Position.X, Cursor.Position.Y);
if (theHandle != null)
{
long res = Win32.SendMessage(theHandle, WM_SETTEXT, IntPtr.Zero, Clipboard.GetText());
}
Note: I'm not entirely sure that WindowFromPiont will get the handle of the child control (i.e. the actual textbox) of another window, rather than the handle of the window itself. You might have to find the child by the cursor position. Been a long time since I've done something like this, unfortunately.
Also, if you want to get a fancier with the acquisition of the window handle, see this question: getting active window name based on mouse clicks in c#
I'm developing a Windows Forms application in C#, which has a multiline TextBox control on a form.
Due to specific (irrelevant) reasons, this TextBox needs a vertical scrollbar on the left side of the TextBox control. I've off course searched for a solution, but I couldn't find any... so my questions are:
1) Is there a way to make the automatic vertical scrollbar of a TextBox control (or a usercontrol derived from TextBox or TextBoxBase) appear on the left instead of the right? This is the preferred method, since all scolling is then still handled by the control. Since chancing the RightToLeft property for such a TextBox actually moves the scrollbar to the left, I feel there must be a hack to be exploited here.
or
2) Is there a message that I can intercept with my IMessageFilter implementation when the TextBox is scrolled, even though it doesn't have scrollbars? I.e. a user can scroll using the arrow keys and the textbox will move lines up and down, but I can't find any messages fired when that occurs.
Maybe another idea of how to accomplish this?
Edit to add: The text needs to be aligned to the right horizontally! Otherwise I would have solved it already.
New edit as of 11/03/2014: Okay, after BenVlodgi's comment I started having doubts about my own sanity. So I created a test project and now I remember why setting RightToLeft to Yes was not working.
The image below shows a regular TextBox on the left with that setting. The scrollbar is on the left and the text on the right, but the text is not shown properly. The period at the end of the sentence is moved in front of the sentence.
The second TextBox control is the one suggested in LarsTech's answer, which functions correctly and does not move any punctuation.
Therefore, I accept and reward the bounty to LarsTech's answer.
I took some of the example code from Rachel Gallen's link and made this version of the TextBox:
public class TextBoxWithScrollLeft : TextBox {
private const int GWL_EXSTYLE = -20;
private const int WS_EX_LEFTSCROLLBAR = 16384;
[DllImport("user32", CharSet = CharSet.Auto)]
public extern static int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32")]
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
protected override void OnHandleCreated(EventArgs e) {
base.OnHandleCreated(e);
int style = GetWindowLong(Handle, GWL_EXSTYLE);
style = style | WS_EX_LEFTSCROLLBAR;
SetWindowLong(Handle, GWL_EXSTYLE, style);
}
}
I've never done it before, but the results seem to have worked:
By setting the RightToLeft property true. But it said the content would also be from right to left, so I don't know if that would solve your problem...But that's a way to set the scrollbar on the left hand side.
http://bytes.com/topic/c-sharp/answers/255138-scrollbar-position
I'm creating a function that takes a RichTextBox and has access to a list of keywords & 'badwords'. I need to highlight any keywords & badwords I find in the RichTextBox while the user is typing, which means the function is called every time an editing key is released.
I've written this function, but the words and cursor in the box flicker too much for comfort.
I've discovered a solution--to disable the RichTextBox's ability to repaint itself while I'm editing and formatting its text. However, the only way I know to do this is to override the "WndProc" function and intercept (what I've been about to gather is) the repaint message as follows:
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if (m.Msg == 0x00f) {
if (paint)
base.WndProc(ref m);
else
m.Result = IntPtr.Zero;
}
else
base.WndProc(ref m);
}
Where the boolean 'paint' is set to false just before I start highlighting and to true when I finish. But as I said, the function I make must take in a RichTextBox; I cannot use a subclass.
So, is there a way to disable the automatic repainting of a RichTextBox 'from the outside?'
It is an oversight in the RichTextBox class. Other controls, like ListBox, support the BeginUpdate and EndUpdate methods to suppress painting. Those methods generate the WM_SETREDRAW message. RTB in fact supports this message, but they forgot to add the methods.
Just add them yourself. Project + Add Class, paste the code shown below. Compile and drop the control from the top of the toolbox onto your form.
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
class MyRichTextBox : RichTextBox {
public void BeginUpdate() {
SendMessage(this.Handle, WM_SETREDRAW, (IntPtr)0, IntPtr.Zero);
}
public void EndUpdate() {
SendMessage(this.Handle, WM_SETREDRAW, (IntPtr)1, IntPtr.Zero);
this.Invalidate();
}
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
private const int WM_SETREDRAW = 0x0b;
}
Or P/Invoke SendMessage directly before/after you update the text.
I haven't accumulated enough points to amend Hans' recommendation. So I added this Answer to mention that it may be necessary to request a repaint by calling InvalidateRect. Some Begin/End Update implementations do this automatically upon the final release of the update lock. Similarly in .Net, Control.Invalidate() can be called which invokes the native InvalidateRect function.
MSDN: Finally, the application can call the InvalidateRect function to cause the list box to be repainted.
See WM_SETREDRAW
Your best bet to accomplish what you are trying to do is to create a multithreaded application. You'll want to create one thread that checks the text against your list. This thread will put any instances it finds into a queue. You'll also want to create another thread that does the actual highlighting of the words. Because you'll need to use BeginInvoke() and Invoke() to update the UI, you'll want to make sure you throttle the rate at which this gets called. I'd so no more then 20 times per second. To do this, you'd use code like this:
DateTime lastInvoke=DateTime.Now;
if ((DateTime.Now - lastInvoke).TotalMilliseconds >=42)
{
lastInvoke=DateTime.Now;
...Do your highlighting here...
}
This thread will check your queue for words that need to be highlighted or re-highlighted and will constantly check the queue for any new updates. Hope this makes sense!