I have a requirement to override the Minimize function of the Telerik radWindow (clicking the Minimize Button on the Title Bar). Instead of the Window Minimizing to the bottom left of the screen I intend to simply reduce the Height of the Window leaving just the Title Bar showing (in the original position). Restoring the Window will again simply set the Height back to its original value to expand the Window….
So, I need to set Handle = true when the SC_MINIMIZE Message is received, this will prevent the Window from minimizing, then i can implement my own code to change the Height of the Window… This is the code so far…
private void RadWindow_HostCreated(object sender, HostWindowCreatedEventArgs e)
{
e.HostWindow.SourceInitialized += HostWindow_SourceInitialized;
}
private void HostWindow_SourceInitialized(object sender, EventArgs e)
{
var source = PresentationSource.FromVisual((Window)sender) as HwndSource;
if (source != null) source.AddHook(new HwndSourceHook(HandleMessages));
}
private IntPtr HandleMessages(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
// 0x0112 == WM_SYSCOMMAND, 'Window' command message.
// 0xF020 == SC_MINIMIZE, command to minimize the window.
if (msg == 0x0112 && ((int)wParam & 0xFFF0) == 0xF020)
{
handled = true; // not catching SC_MINIMIZE here
}
return IntPtr.Zero;
}
However, while I seem to be catching Windows Messages in the HandleMessages function, it is not setting handled = true; when I click the Minimize Button…
Any help would be appreciated…
Related
A WinForms application, in which a certain UI control has to disappear 5 seconds after the user interacts with the window (clicking anywhere on the form including any control, or key presses).
Assuming an event is fired when this happens, the following is the event handler:
private async void userInteract(object sender, System.EventArgs e)
{
if (progressBarFinished)
{
await Task.Delay(5000);
statusIdle(); // this method hides a progress bar after 5 seconds. It is working.
}
}
In the form constructor, the event is subscribed to as follows:
// at the moment, it is not working for when a user clicks anywhere on the form
// it is working when a specific control click event occurs, like this one
progressBar.Click += userInteract;
Subscribing to the MouseClick and KeyPress events of the Form itself have been tried, but the event does not seem to fire then. It's only when specific control events are used, that it works, as stated above.
A form’s WndProc method processes messages sent to the form by the Windows operating system. This is an extremely important method that allows forms to move, resize, repaint, and perform other critical operations.
// Constants for decoding the Win32 message.
protected const int WM_MOUSEACTIVATE = 0x0021;
protected const int WM_LBUTTONDOWN = 0x201;
protected const int WM_RBUTTONDOWN = 0x204;
protected override void WndProc(ref Message m)
{
// Check the Message parameter to see if the message is WM_MOUSEACTIVATE indicating that a control was clicked.
if (m.Msg == WM_MOUSEACTIVATE)
{
int wparam = m.WParam.ToInt32();
if (wparam == WM_LBUTTONDOWN || wparam == WM_RBUTTONDOWN)
{
// TODO: Do something with the mouse event.
Console.WriteLine(m);
return;
}
}
base.WndProc(ref m);
}
Ref 1
Ref 2
I am developing a Windows Forms application in C# in which I have a form which must start in a maximized state and not allow users to restore or resize it. I have already configured the form to start in maximized mode, disable the restore and maximize button and locked the borders of the form but when the title bar is double clicked, the form restores to a smaller size which is unexpected. The following are the properties I set to achieve the required behaviour:
FormBorderStyle = FixedSingle
MaximizeBox = False
WindowState = Maximized
Can someone please help me solve this problem and explain me the solution?
Thanks in advance.
You have to remember that your form starts with some default size values and double click is just toggling between 2 states.
Within your normal state the form will retrieve it's last ( in your case default ) size which you can override :
Width = Screen.PrimaryScreen.Bounds.Width;
Height = Screen.PrimaryScreen.Bounds.Height;
Another thing is that your application has something called start position which ( from what I remember ) defaults to the center of the screen and you can change it using :
Form.StartPosition = new Point(0, 0); // top-left corner
Now all you have to do in your applicaiton is to check for the toggle between window states. Easiest way would be to use WndProc and wait for messages listed in this msdn page :
protected override void WndProc(ref Message m)
{
const int WM_SYSCOMMAND = 0x0112;
const int SC_MAXIMIZE = 0xF030;
const int SC_RESTORE = 0xF120;
if (m.Msg == WM_SYSCOMMAND)
{
switch((int)m.WParam)
{
case SC_RESTORE:
// your window was restored ( double clicked on the command bar )
// set it's window state back to maximize or do whatever
break;
case SC_MAXIMIZE:
// your window was maximized .. no actions needed, just for debugging purpose
break;
}
}
base.WndProc(ref m);
}
This can be accomplished by catching the event and overriding it:
private void Form_Load(object sender, EventArgs e)
{
this.FormBorderStyle = FormBorderStyle.FixedSingle;
this.WindowState = FormWindowState.Maximized;
this.MaximizeBox = false;
this.MinimumSize = Screen.GetWorkingArea(this.Location).Size;
}
private const int WM_NCLBUTTONDBLCLK = 0x00A3;
//double click on a title bar
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_NCLBUTTONDBLCLK)
{
m.Result = IntPtr.Zero;
return;
}
base.WndProc(ref m);
}
I am subclassing TextBox:
class Editor : TextBox
I have overridden OnKeyDown, because I want tabs to be replaced by four spaces:
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyCode == Keys.Tab) {
SelectedText = " ";
e.SuppressKeyPress = true;
}
}
This works, but unfortunately it also clears the undo buffer. The end result is that when the user presses tab, Ctrl+Z doesn't work and 'Undo' on the right-click menu becomes disabled. The problem appears to be the "e.SuppressKeyPress = true;" part.
Does anyone have any idea of how to get around this?
For more info, I am creating a fairly simple text editor, and I'm handling not only the Tab key (as above), but also the Enter key. So I have this problem with Tab and Enter. I am aware that this problem doesn't exist with RichTextBox, but for various reasons I want to use TextBox instead.
Any help would be much appreciated, as this is a show-stopping problem in my project.
Thanks,
Tom
This isn't a result of overriding OnKeyDown, it's that you're setting SelectedText (any text modification will have the same effect). You can see this by commenting out your code that sets the SelectedText while leaving everything else. Obviously you won't get a tab or four characters, but the undo buffer will be preserved.
According to this blog post, you should be able to use the Paste(string) function rather than setting the SelectedText property and preserve the undo buffer:
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyCode == Keys.Tab)
{
Paste(" ");
e.SuppressKeyPress = true;
}
}
I've finally found the solution, which is to use the Windows API as follows:
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyCode == Keys.Tab) {
WinApi.SendMessage(Handle, WinApi.WmChar, WinApi.VkSpace, (IntPtr)4);
e.SuppressKeyPress = true;
}
base.OnKeyDown(e);
}
Here is my WinApi class:
using System;
using System.Runtime.InteropServices;
class WinApi
{
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
public const UInt32 WmChar = 0x102;
public static readonly IntPtr VkSpace = (IntPtr)0x20;
}
I found that when I attach a MouseWheel event to my UserControl or a TextBox, it does not trigger if the TextBox is scrollable. It will scroll the textbox and not trigger MouseWheel, can I make it such that it runs MouseWheel and then after doing something e.Cancel it so that the TextBox does not scroll?
UPDATE: With Video & Code
Video
http://screenr.com/ZGF
Code
http://www.mediafire.com/?x3o09dz6dr5zoym
public MainWindow()
{
InitializeComponent();
textBox.MouseWheel += (s, e) =>
{
Random rand = new Random();
Debug.WriteLine(rand.NextDouble());
};
}
I assume you mean that the MouseWheel event on the UserControl won't trigger. That's normal, the TextBox is happy to accept the message when it is multiline. The reason that the MouseWheel event is not visible in the designer. The parent window will only see the message when the control with the focus won't process it.
Not sure if you should fix this, the user would really expect the text box to scroll. But you can by intercepting the message so the text box can't see it and passing the message to the parent. Add a new class to your project, paste the code shown below. Compile. Drop the new control from the top of the toolbox.
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
class MyTextBox : TextBox {
protected override void WndProc(ref Message m) {
if (m.Msg == 0x20a && this.Parent != null) {
PostMessage(this.Parent.Handle, m.Msg, m.WParam, m.LParam);
}
else base.WndProc(ref m);
}
[DllImport("user32.dll")]
private static extern IntPtr PostMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
}
I made a custom window for my app and I wrote some code if a user clicks my custom maximize button:
private void MaxThis(object sender, System.Windows.RoutedEventArgs e)
{ if (WindowState == WindowState.Maximized){
WindowState = WindowState.Normal;}
else {
this.Top = 0;
this.Left = 0;
this.MaxWidth = System.Windows.SystemParameters.WorkArea.Width;
this.MaxHeight = System.Windows.SystemParameters.WorkArea.Height;
this.WindowState = WindowState.Maximized;
}
}
The restoring to the normal state works fine. However when I want to maximize, it maximizes the window with a small margin on the right and bottom of the screen. Clicking maximize again fixes this somehow. How do I fix this to maximize at the first click...?
Take away the Height and Width properties you have set in XAML for your window
Try to use just
this.WindowState = WindowState.Maximized;
Perhaps code, goes before messing Windows API action.
Sorry, my mistake.
Then you should use Windows API to raise Maximize event.
Try this code:
[DllImport("user32.dll")]
public static extern int SendMessage(
int hWnd, // handle to destination window
uint Msg, // message
long wParam, // first message parameter
long lParam // second message parameter
);
public const int WM_SIZE = 0x0005;
public const int SIZE_MAXIMIZED = 2;
And in your click event:
SendMessage(this.Handle, WM_SIZE, SIZE_MAXIMIZED, 0);