In my form, I'm using a tabcontrol. I want to hide the tab headers and border both. I can do either one, if I try to hide the headers then the border becomes visible. Can anyone help me, please? thanks and here's my code:
public Form3()
{
InitializeComponent();
this.NativeTabControl1 = new NativeTabControl();
this.NativeTabControl1.AssignHandle(this.tabControl1.Handle);
}
private NativeTabControl NativeTabControl1;
private class NativeTabControl : NativeWindow
{
protected override void WndProc(ref Message m)
{
if ((m.Msg == TCM_ADJUSTRECT))
{
RECT rc = (RECT)m.GetLParam(typeof(RECT));
//Adjust these values to suit, dependant upon Appearance
rc.Left -= 3;
rc.Right += 3;
rc.Top -= 3;
rc.Bottom += 3;
Marshal.StructureToPtr(rc, m.LParam, true);
}
base.WndProc(ref m);
}
private const Int32 TCM_FIRST = 0x1300;
private const Int32 TCM_ADJUSTRECT = (TCM_FIRST + 40);
private struct RECT
{
public Int32 Left;
public Int32 Top;
public Int32 Right;
public Int32 Bottom;
}
private void Form3_Load(object sender, EventArgs e)
{
//hides tabcontrol headers
tabControl1.Appearance = TabAppearance.Buttons;
tabControl1.ItemSize = new Size(0, 1);
tabControl1.SizeMode = TabSizeMode.Fixed;
}
}
There is another thread on Stackoverflow, which provides some ideas to hide the tab row of the TabControl in Windows Forms.
My favorite one is to override WndProc and set the Multiline property to true.
public partial class TabControlWithoutHeader : TabControl
{
public TabControlWithoutHeader()
{
if (!this.DesignMode) this.Multiline = true;
}
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x1328 && !this.DesignMode)
m.Result = new IntPtr(1);
else
base.WndProc(ref m);
}
}
I tested the code on Windows 8.1 and see neither the tabs nor a border line. So I think you do not need to use code like you posted.
I would usually suggest doing this in the xaml not C# (I'm a WPF developer) I believe you can do it in the C# as well by naming both the TabControl as well as each Tab itself.
tabControlName.BorderBrush = null;
///^Gets rid of the TabControl's border.
tabName1.Height = 0;
tabName2.Height = 0;
tabNameETC.Height = 0;
///^Removes the tabs(headers) if you have the TabControl.TabStripPlacement set to left
/// or right, then use the following instead:
tabName1.Width = 0
tabName2.Width = 0
tabNameETC.Width = 0
Related
I like to have my form borderless in C#. So I used this code:
FormBorderStyle = FormBorderStyle.None;
But it removes the aero effect of windows 8. The form opens suddenly like a blink.
How can i bring the aero effect back?
I am answering my own question using the C++ reference
I wrote a class inherited from Form Class. Each form in application should be inherited from this class instead of Form Class.
public class AeroForm : Form
{
int _w = 100, _h = 100;
bool aero = false;
[StructLayout(LayoutKind.Sequential)]
struct MARGINS { public int Left, Right, Top, Bottom; }
[DllImport("dwmapi.dll", PreserveSig = false)]
static extern void DwmExtendFrameIntoClientArea
(IntPtr hwnd, ref MARGINS margins);
[DllImport("dwmapi.dll", PreserveSig = false)]
static extern bool DwmIsCompositionEnabled();
public AeroForm()
{
aero = IsCompositionEnabled();
}
public AeroForm(int width, int height)
: this()
{
_w = width;
_h = height;
Size = new Size(width, height);
}
protected override void WndProc(ref Message m)
{
const int WM_NCCALCSIZE = 0x0083;
switch (m.Msg)
{
case WM_NCCALCSIZE:
if (aero)
return;
break;
}
base.WndProc(ref m);
}
//this is for checking the OS's functionality.
//Windows XP does not have dwmapi.dll
//also, This corrupts the designer...
//so i used the Release/Debug configuration
bool IsCompositionEnabled()
{
#if !DEBUG
return File.Exists(Environment.SystemDirectory + "\\dwmapi.dll")
&& DwmIsCompositionEnabled();
#else
return false;
#endif
}
//this one is used for a shadow when aero is not available
protected override CreateParams CreateParams
{
get
{
const int CS_DROPSHADOW = 0x00020000;
const int WS_MINIMIZEBOX = 0x20000;
const int CS_DBLCLKS = 0x8;
CreateParams cp = base.CreateParams;
if (!aero)
cp.ClassStyle |= CS_DROPSHADOW;
cp.Style |= WS_MINIMIZEBOX;
cp.ClassStyle |= CS_DBLCLKS;
return cp;
}
}
//this is for aero shadow and border configurations
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (aero)
{
FormBorderStyle = FormBorderStyle.FixedSingle;
ControlBox = false;
MinimizeBox = false;
MaximizeBox = false;
Size = new Size(_w, _h);
MARGINS _glassMargins = new MARGINS()
{
Top = 5,
Left = 5,
Bottom = 5,
Right = 5
};
DwmExtendFrameIntoClientArea(this.Handle, ref _glassMargins);
}
else
FormBorderStyle = FormBorderStyle.None;
}
//When you minimize and restore, the size will change.
//this override is for preventing this unwanted resize.
protected override void OnPaint(PaintEventArgs e)
{
if (aero)
Size = new Size(_w, _h);
base.OnPaint(e);
}
}
with Show() and Application.Run() it works great!
but it has some regressions when the form opens with ShowDialog(). Closing the form, you will see a border that closes after your client content hides.
Inside my richtextbox have a checkbox, when scroll down or up my richtextbox, checkbox not scrolling whit it.
CheckBox chk = new CheckBox();
chk.Name = "Chk" + i;
chk.Location = new Point(80,10+i);
chk.Text = "Save";
chk.Size = new System.Drawing.Size(20, 100);
richTextBox1.Controls.Add(chk);
i++;
Can you tell me how to solve it.
A RichTextBox cannot contain a CheckBox object. and you have set static point for location of your checkpoint
chk.Location = new Point(80,10+i)
, and it is over RichTextBox , not into that
You can handle the MouseWheel and Scroll events of your RichTextBox and use the GetScrollPos win32 function to get the new position of the scrollbar of your RichTextBox, then update the position of your CheckBox accordingly. Notice that when the MouseWheel is raised, the position of the ScrollBar is not changed to the new one immediately, it will be changed smoothly from the current to the new one. That's why we have to use a Timer to call the GetScrollPos repeatedly an periodically until the return position is the same. The effect we get is not perfect as the smoothness of the scrollbar moving but it's close to that smoothness and far better than calling the GetScrollPos once right in the MouseWheel event handler.
However in this code, I would like to use NativeWindow to hook into the message loop and fetch the messages sent to the RichTextBox, here is the code which works OK, this code is just a demo and handle the Vertical scrolling only. You can find more info on WM_HSCROLL and GetScrollPos to handle the Horizontal scrolling (it's easy because it's very much similar to the Vertical scrolling):
public partial class Form1 : Form
{
[DllImport("user32")]
private static extern int GetScrollPos(IntPtr hwnd, int nBar);
public Form1()
{
InitializeComponent();
chk.Text = ".NET pro";
chk.Parent = richTextBox1;
chk.Top = 100;//Notice the initial Top to update the position properly later.
nativeRichText.AssignHandle(richTextBox1.Handle);
//Scroll event handler for the nativeRichText
nativeRichText.Scroll += (s, e) =>
{
chk.Top = 100-e.Y;
};
//TextChanged event handler for the richTextBox1
richTextBox1.TextChanged += (s, e) =>
{
chk.Top = 100-GetScrollPos(richTextBox1.Handle, 1);
};
}
CheckBox chk = new CheckBox();
NativeRichTextBox nativeRichText = new NativeRichTextBox();
public class NativeRichTextBox : NativeWindow
{
Timer t = new Timer();
int y = -1;
public NativeRichTextBox()
{
t.Interval = 30;
t.Tick += (s, e) =>
{
int y2 = Form1.GetScrollPos(Handle, 1);//nBar =1 => Vertical bar
if (y2 == y) { t.Stop(); return; }
y = y2;
if (Scroll != null) Scroll(this, new ScrollEventArgs(0, y));
};
}
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x115)//WM_VSCROLL = 0x115
{
int wp = m.WParam.ToInt32();
int low = wp & 0x00ff;
if (low == 4 || low == 5)//SB_THUMBPOSITION = 4 SB_THUMBTRACK = 5
{
if (Scroll != null) Scroll(this, new ScrollEventArgs(0, wp >> 16));
}
else t.Start();
}
if (m.Msg == 0x20a)//WM_MOUSEWHEEL = 0x20a
{
y = -1;
t.Start();
}
base.WndProc(ref m);
}
public class ScrollEventArgs : EventArgs
{
public int X { get; set; }
public int Y { get; set; }
public ScrollEventArgs(int x, int y)
{
X = x;
Y = y;
}
}
public delegate void ScrollEventHandler(object sender, ScrollEventArgs e);
public event ScrollEventHandler Scroll;
}
}
Most probably you have seen around checkboxes inside comboboxes or dropdown lists.
It is possible to do it. You may try with third parties controls like this, or code your own. This topic was already discussed in another question on SO, have a look here, so we do not restart debating the same topic in this question.
What you are obtaining with your code instead, is just to put graphically one control on another but they do not interact to each other. They are two separate controls.
a program of mine uses AxShockwaveFlash component used as stream player.
The problem is that my code works with most stream-providers (livestream, ustream, own3d.tv) but Justin.TV's player is somewhat problematic.
Before moving on the actual problem let me summarize my code;
Inherited FlashControl - this allows me to override the flashplayer's built-in menu:
public class FlashPlayer : AxShockwaveFlashObjects.AxShockwaveFlash // Customized Flash Player.
{
private const int WM_MOUSEMOVE = 0x0200;
private const int WM_MOUSEWHEEL = 0x020A;
private const int WM_LBUTTONDOWN = 0x0201;
private const int WM_LBUTTONUP = 0x0202;
private const int WM_LBUTTONDBLCLK = 0x0203;
private const int WM_RBUTTONDOWN = 0x0204;
private const int WM_RBUTTONUP = 0x0205;
public new event MouseEventHandler DoubleClick;
public new event MouseEventHandler MouseDown;
public new event MouseEventHandler MouseUp;
public new event MouseEventHandler MouseMove;
public FlashPlayer():base()
{
this.HandleCreated += FlashPlayer_HandleCreated;
}
void FlashPlayer_HandleCreated(object sender, EventArgs e)
{
this.AllowFullScreen = "true";
this.AllowNetworking = "all";
this.AllowScriptAccess = "always";
}
protected override void WndProc(ref Message m) // Override's the WndProc and disables Flash activex's default right-click menu and if exists shows the attached ContextMenuStrip.
{
if (m.Msg == WM_LBUTTONDOWN)
{
if (this.MouseDown != null) this.MouseDown(this, new MouseEventArgs(System.Windows.Forms.MouseButtons.Left, 1, Cursor.Position.X, Cursor.Position.Y, 0));
}
else if (m.Msg == WM_LBUTTONUP)
{
if (this.MouseUp != null) this.MouseUp(this, new MouseEventArgs(System.Windows.Forms.MouseButtons.None, 0, Cursor.Position.X, Cursor.Position.Y, 0));
}
else if (m.Msg == WM_MOUSEMOVE)
{
if (this.MouseMove != null) this.MouseMove(this, new MouseEventArgs(System.Windows.Forms.MouseButtons.None, 0, Cursor.Position.X, Cursor.Position.Y, 0));
}
else if (m.Msg == WM_RBUTTONDOWN)
{
if (this.ContextMenuStrip != null) this.ContextMenuStrip.Show(Cursor.Position.X, Cursor.Position.Y);
m.Result = IntPtr.Zero;
return;
}
else if (m.Msg == WM_LBUTTONDBLCLK)
{
if (this.DoubleClick != null) this.DoubleClick(this, new MouseEventArgs(System.Windows.Forms.MouseButtons.Left, 2, Cursor.Position.X, Cursor.Position.Y, 0));
m.Result = IntPtr.Zero;
return;
}
base.WndProc(ref m);
}
}
Player window code: (Player is an instance of FlashPlayer)
private void Player_Load(object sender, EventArgs e)
{
try
{
this.Text = string.Format("Stream: {0}", this._stream.Name); // set the window title.
this.Player.LoadMovie(0, this._stream.Movie); // load the movie.
if (this._stream.ChatAvailable && Settings.Instance.AutomaticallyOpenChat) this.OpenChatWindow();
}
catch (Exception exc)
{
// log stuff.
}
}
So this works great for livestream.com, ustream.com, own3d.tv but when it come's to justin.tv's player i'm getting a 1337 error (invalid embed code). So i tried to ask them for support but could't get a valid answer.
_stream.movie variable actually holds a valid URL for the stream source like;
http://cdn.livestream.com/grid/LSPlayer.swf?channel=%slug%&autoPlay=true (livestream sample)
or
http://www.justin.tv/widgets/live_embed_player.swf?channel=%slug%&auto_play=true&start_volume=100 (justin.tv sample)
Tried to urlencode the 'channel=%slug%&auto_play=true&start_volume=100' part for justin.tv but that did not work also.
So i started trying some work-arounds which at first place i thought setting flashVars variable of the control.
But i've a strange problem there, whenever i try to set flashVars variable it never get's set. I found a sample screenshot on the issue;
So if i was able to set the flashVariables may be i could work-around the justin.tv player's error. Btw, i also tried setting variables using Player.SetVariable(key,value) - that didn't work also.
Notes:
I'm running on .net 4.0 client profile.
Using the Flash10l.ocx.
Have generated the AxShockwaveFlashObjects.dll, ShockwaveFlashObjects.dll wrappers using "aximp.exe –source "C:\WINDOWS\system32\Macromed\Flash\Flash10l.ocx"
I recently had an issue with making justin.tv work, but in the end it was as simple as
axShockwaveFlash1.FlashVars = "auto_play=true&channel=adventuretimed&start_volume=25";
axShockwaveFlash1.Movie = "http://www.justin.tv/widgets/live_embed_player.swf";
and it works perfectly
Is there anyway to control where you can move a form?
So if i move a form, it can only be moved on the vertical axis and when i try to move it horizontally, nothing happens.
I dont want a buggy implementation like locationchanged or move event and poping it back inline. I no there is a way using something like a WndProc override but after searching for a while, i couldnt find anything. Please help
For example:
using System.Runtime.InteropServices;
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x216) // WM_MOVING = 0x216
{
Rectangle rect =
(Rectangle) Marshal.PtrToStructure(m.LParam, typeof (Rectangle));
if (rect.Left < 100)
{
// compensates for right side drift
rect.Width = rect.Width + (100 - rect.Left);
// force left side to 100
rect.X = 100;
Marshal.StructureToPtr(rect, m.LParam, true);
}
}
base.WndProc(ref m);
}
The above code sets a minimum lefthand position of 100.
There is no need to recreate the RECT structure, like driis did, the .NET native Rectangle works fine. However, you have to set the location via the X property, since Left is a Get only property.
You would most likely want to override WndProc and handle the WM_MOVING message. According to MSDN:
The WM_MOVING message is sent to a
window that the user is moving. By
processing this message, an
application can monitor the position
of the drag rectangle and, if needed,
change its position.
This would be a way to do it, however, you would obviously need to tweek it for your needs:
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace VerticalMovingForm
{
public partial class Form1 : Form
{
private const int WM_MOVING = 0x0216;
private readonly int positionX;
private readonly int positionR;
public Form1()
{
Left = 400;
Width = 500;
positionX = Left;
positionR = Left + Width;
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_MOVING)
{
var r = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT));
r.Left = positionX;
r.Right = positionR;
Marshal.StructureToPtr(r, m.LParam, false);
}
base.WndProc(ref m);
}
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
}
}
VB.NET Version:
Protected Overloads Overrides Sub WndProc(ByRef m As Message)
If m.Msg = &H216 Then
' WM_MOVING = 0x216
Dim rect As Rectangle = DirectCast(Marshal.PtrToStructure(m.LParam, GetType(Rectangle)), Rectangle)
If rect.Left < 100 Then
' compensates for right side drift
rect.Width = rect.Width + (100 - rect.Left)
' force left side to 100
rect.X = 100
Marshal.StructureToPtr(rect, m.LParam, True)
End If
End If
MyBase.WndProc(m)
End Sub
How would i go about stopping a form from being moved. I have the form border style set as FixedSingle and would like to keep it this way because it looks good in vista :)
Take a look at this link. You might be interested in option #3. It will require you to wrap some native code, but should work. There's also a comment at the bottom of the link that shows an easier way to do it. Taken from the comment (can't take credit for it, but I'll save you some searching):
protected override void WndProc(ref Message message)
{
const int WM_SYSCOMMAND = 0x0112;
const int SC_MOVE = 0xF010;
switch(message.Msg)
{
case WM_SYSCOMMAND:
int command = message.WParam.ToInt32() & 0xfff0;
if (command == SC_MOVE)
return;
break;
}
base.WndProc(ref message);
}
You can set the FormBorderStyle property of the Form to None
this.FormBorderStyle=System.Windows.Forms.FormBorderStyle.None
I found this to stop the form from moving (its in c#)
protected override void WndProc(ref Message m)
{
const int WM_SYSCOMMAND = 0x0112;
const int SC_MOVE = 0xF010;
switch (m.Msg)
{
case WM_SYSCOMMAND:
int command = m.WParam.ToInt32() & 0xfff0;
if (command == SC_MOVE)
return;
break;
}
base.WndProc(ref m);
}
Found here
Try to override WndProc:
protected override void WndProc(ref Message m)
{
const int WM_NCLBUTTONDOWN = 161;
const int WM_SYSCOMMAND = 274;
const int HTCAPTION = 2;
const int SC_MOVE = 61456;
if ((m.Msg == WM_SYSCOMMAND) && (m.WParam.ToInt32() == SC_MOVE))
{
return;
}
if ((m.Msg == WM_NCLBUTTONDOWN) && (m.WParam.ToInt32() == HTCAPTION))
{
return;
}
base.WndProc(ref m);
}
It's not all pretty (there is some flashing going on when you try to move the form), but you can use the LocationChanged property to keep the form where you want it:
private Point _desiredLocation;
// assign the _desiredLocation variable with the form location at some
// point in the code where you know that the form is in the "correct" position
private void Form_LocationChanged(object sender, EventArgs e)
{
if (this.Location != _desiredLocation)
{
this.Location = _desiredLocation;
}
}
Out of curiousity; why would you want to do this?
In Windows, the WS_CAPTION style is the non-client area that allows your window to be moved with a mouse. So the easiest way to do what you want is to remove this style from your window.
However, if you need to have a caption and still achieve what you want, then the next style would be to capture the WM_NCHITTEST message and check for HTCAPTION. If the code is HTCAPTION, return NTNOWHERE instead. This will prevent the default window procedure from executing the default move window thing.
It's not a good practice to make your form immovable. I'd think agfain about it if I were you.
Anyway, you can do this by overridding the WinProc to disable the [Move] menuitem from the system menu.
[DllImport("user32.dll")]
private static extern Int32 EnableMenuItem ( System.IntPtr hMenu , Int32uIDEnableItem, Int32 uEnable);
private const Int32 HTCAPTION = 0×00000002;
private const Int32 MF_BYCOMMAND =0×00000000;
private const Int32 MF_ENABLED =0×00000000;
private const Int32 MF_GRAYED =0×00000001;
private const Int32 MF_DISABLED =0×00000002;
private const Int32 SC_MOVE = 0xF010;
private const Int32 WM_NCLBUTTONDOWN = 0xA1;
private const Int32 WM_SYSCOMMAND = 0×112;
private const Int32 WM_INITMENUPOPUP = 0×117;
protected override void WndProc(ref System.Windows.Forms.Message m )
{
if (m.Msg == WM_INITMENUPOPUP)
{
//handles popup of system menu
if ((m.LParam.ToInt32() / 65536) != 0) // 'divide by 65536 to get hiword
{
Int32 AbleFlags = MF_ENABLED;
if (!Moveable)
{
AbleFlags = MF_DISABLED | MF_GRAYED; // disable the move
}
EnableMenuItem(m.WParam, SC_MOVE, MF_BYCOMMAND | AbleFlags);
}
}
if (!Moveable)
{
if (m.Msg == WM_NCLBUTTONDOWN) //cancels the drag this is IMP
{
if (m.WParam.ToInt32() == HTCAPTION) return;
}
if (m.Msg == WM_SYSCOMMAND) // Cancels any clicks on move menu
{
if ((m.WParam.ToInt32() & 0xFFF0) == SC_MOVE) return;
}
}
base.WndProc(ref m);
}
Also, you can handle OnMove event of your form. But I think this will cause some flickering:
private void Form1_Move(object sender, EventArgs e)
{
this.Location = defaultLocation;
}
Just change the FormBorderStyle property to None.
change the Form property StartPostion to Manual.
Then, handle the LocationChanged event:
private void frmMain_LocationChanged(object sender, EventArgs e)
{
Location = new Point(0, 0);
}
Go to form events-> Location changed
write the following code
Location = new Point(this.Width,this.Height);
I would question your need to make the form unmovable. This doesn't sound nice. You could of course save the location of the window when the window closes and reopen the window into that position. That gives the user some control over where the window should be located.
You can subscribe to the Form.Move event and reposition from it.
Just reset the location on formlocation_changed event to where it was i.e. set the Form.Location to a variable before it's moved and when the user tries to move it, it will go back to the variable location you set it to.
Private Sub MyFormLock()
Me.Location = New Point(0, 0)
End Sub
Private Sub SearchSDR_LocationChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.LocationChanged
Call MyFormLock()
End Sub
You can try:
this.Locked = true;