|
Hi,
Completely redrawing over the scrollbar is not easy and it requires you to do a lot more then the above.
To get a flat text box, you can simply do:
- Create a textbox and set the border to FixedSingle
- The standard border is quite awful, so you can use similar method to above to draw the border of your prefered colour or style
I haven't tried to paint over scrollbar before, but I believe you will need to trap the scroll event as well
Fadrian
|
|
|
|
|
I can't seem to get this working in vs2005, even though in vs2003 it all works fine. Its reporting the following error:
A call to PInvoke function 'ELSA 1.1!ELSA.FlatComboBox::SendMessage' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
relating to line 108:
switch (m.Msg)<br />
{<br />
case WM_NC_PAINT: <br />
hDC = GetWindowDC(this.Handle);<br />
gdc = Graphics.FromHdc(hDC);<br />
SendMessage(this.Handle, WM_ERASEBKGND, hDC, 0);
SendPrintClientMsg();
PaintFlatControlBorder(this, gdc);<br />
m.Result = (IntPtr) 1;
ReleaseDC(m.HWnd, hDC);<br />
gdc.Dispose(); <br />
<br />
break;<br />
At the moment I am struggling to fix it. Any ideas?
|
|
|
|
|
Hi,
I tested and it actually works fine. I start to suspect it is either the installed framework is corrupted or perhaps you have a later operating system then what I'm running?
Also, if you are using VS2005, wouldn't it be just as easy to just use the standard combobox provided - which is now have the proper flat mode?
Fadrian
|
|
|
|
|
If it works fine for you then I am baffled. It works fine in 2003 but in 2005 it comes up with the above error. I am using Windows XP, and haven't encountered any other problems which could be related to corrupt framework.
The reason that I was hoping your combobox would work was that I have been using the flatmode provided by vs2005, but it has no support for a black border. What I am finding frustrating is that if you set textboxes to border style none they immediately shrink and only just fit around the text. Meanwhile comboboxes set to flatstyle still remain fat with plenty of padding inside. The solution to this is set textboxes to borderstyle fixedsingle, which remain fat - approx in proportion to comboboxes, but then there is a black border around all the textboxes that I cannot work out how to put around the comboboxes.
I was hoping your combobox would work as it has the black border! and looks neater. Any help would be hugely appreciated.
|
|
|
|
|
I initially tested on Beta 2, just because the PC on hand only had that and it was fine. Getting your reply I loaded the full vs2005 and get the same error! sorry for the confusion.
I got the fix for it.
Change the declaration to
[DllImport("user32.dll", EntryPoint="SendMessageA")]
public static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
and in the code where you use the DC, you will have to do .ToInt32()
SendMessage(this.Handle, WM_ERASEBKGND, hDC.ToInt32(), 0);
and that will fix it.
Seem like .NET 2.0 is very strict with the pinvoke signature. In WINAPI, SendMessage does use DWORD for the param which should really be mapping to int32, but in .NET 1.1 if you do so, it give you another set of issues to workaround with.
Fadrian
|
|
|
|
|
Hi
Thnx it works 4 me as well in VS2005 thnx
|
|
|
|
|
Like many who use The Code Project we've spent countless hours building custom controls to meet our needs. Unfortunately, it's hard to justify spending thousands of hours on a custom control unless you intend to market them.
We've just released a beta of List Controls for .NET WinForms which includes the most advanced list box and combo box controls ever built for any platform.
Sounds too good to be true? Please, confirm this statement for yourself. A beta of List Controls is available for download from our website, including a comprehensive demo and tutorial.
http://www.it-partners.com/products/list_controls_win_forms/list_controls.asp[^]
Many features, too many to list here!
Brett Werner
it-partners.com
|
|
|
|
|
I want to use color in combo box and arow and background color of combo box.
plz help me how can i change it through CSS classes.
Ajay
Advance Scripter
|
|
|
|
|
Hi Ajay,
Unfortunately to my knowledge, you can only use css style with web control and not winform control. I would think to implement support for css will involve a lot of work.
I dont use css much and I would welcome pointers from others.
Fadrian
|
|
|
|
|
Hi,
I've slightly changed your control for my purpose and add colored border
onto it, problem is however with inner listbox. I think I will propably have to subclass it and redirect WM_NCPAINT to fake WndProc function, when I'll draw border of listbox in appropriate color. Do you plan to add this behaviour to your control? If you have it already, please let me know, I would like to save some time in writing it.
Thanks
Martin
martinhoge@seznam.cz
|
|
|
|
|
Martin,
I haven't done anything on that area yet. If you have done something it will be nice if you can share your work here.
Thanks,
Fadrian
|
|
|
|
|
There is a problem when i change RightToLeft property to Yes
|
|
|
|
|
Booky,
Thanks for pointing that out. It is something that I haven't looked at before
Well, I did a quick hack just then and it works for me. Below is the snipplet of the code that will do the job. Replace the original PaintFlatDropDown function with the revised code below.
private static bool DrawRightToLeft(Control ctrl)
{
if (ctrl.RightToLeft == RightToLeft.Yes ||
(ctrl.RightToLeft == RightToLeft.Inherit && ctrl.Parent.RightToLeft == RightToLeft.Yes))
{
return true;
}
return false;
}
public static void PaintFlatDropDown(Control ctrl, Graphics g)
{
Rectangle rect = new Rectangle(ctrl.Width-DropDownButtonWidth, 0, DropDownButtonWidth, ctrl.Height);
if (DrawRightToLeft(ctrl))
rect = new Rectangle(1, 0, DropDownButtonWidth, ctrl.Height);
ControlPaint.DrawComboButton(g, rect, ButtonState.Flat);
}
Hope that help.
Fadrian
|
|
|
|
|
flickering !!
If there are so much combobox in the same form, flickering is increaseing. Because Windows drawing the normal combobox before our painting.
Serdar YILMAZ
Senior Developer
|
|
|
|
|
Adding following code will not make flickering any more!!
protected override void OnPaint(PaintEventArgs e)
{
// base.OnPaint (e);
}
switch (m.Msg)
{
...
case WM_ERASEBKGND:
//indicate msg has been processed
m.Result = (IntPtr) 1;
break;
...
Thanks,
ChangYoung
jucyblue@gmail.com
jucyblue@gmail.com
|
|
|
|
|
Has no change ...
Serdar YILMAZ
Senior Developer
|
|
|
|
|
Thanks for the post and suggestion. I really don't have much idea on how to fix that, as my control is drawing on top of existing control to leverage all the existing functionality. If someone has a solution to this I will be please to know.
Fadrian
|
|
|
|
|
I changed Draw Mode of this control.
Now, there are NO flicker.
And I added ImageList properties.
public syComboBox()
{
...
...
base.SetStyle(ControlStyles.ResizeRedraw, true);
this.DrawMode = DrawMode.OwnerDrawVariable;
}
...
...
protected virtual void Draw(bool fillContent)
{
Graphics graphics1 = Graphics.FromHwnd(base.Handle);
// Drawing Border
... drawing border procedures
... if (this.isMouseOver | this.Focused) then draw HOT else draw NORMAL
// Drawing Button
ButtonState bs = (DroppedDown) ? ButtonState.Pushed : ButtonState.Normal;
... drawing combobox button procedures
if (fillContent)
{
Rectangle rectangle1 = (1, 1, this.Width-SystemInformation.HorizontalScrollBarArrowWidth-2, this.Height-2);
Color color1 = this.BackColor;
if (!base.Enabled)
{
color1 = SystemColors.Control;
}
SolidBrush brush1 = new SolidBrush(color1);
graphics1.FillRectangle(brush1, 1, 1, rectangle1.Width, 2); // top
graphics1.FillRectangle(brush1, 1, rectangle1.Bottom - 2, rectangle1.Width, 2); // bottom
graphics1.FillRectangle(brush1, 1, 1, 2, rectangle1.Height); // left
graphics1.FillRectangle(brush1, rectangle1.Right - 2, 1, 2, rectangle1.Height); // right
}
}
...
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
this.isMouseOver = false;
this.Draw(false);
}
protected override void OnMouseEnter(EventArgs e)
{
base.OnMouseEnter(e);
this.isMouseOver = true;
this.Draw(false);
}
protected override void OnLostFocus(System.EventArgs e)
{
base.OnLostFocus(e);
this.Draw(false);
}
protected override void OnGotFocus(System.EventArgs e)
{
base.OnLostFocus(e);
this.Draw(false);
}
protected override void WndProc(ref Message msg)
{
if (msg.Msg == 15)
{
base.DefWndProc(ref msg);
this.Draw(true);
}
else
{
base.WndProc(ref msg);
}
}
-----------------
Serdar YILMAZ
Senior Developer
|
|
|
|
|
please, can you post the modified source ?
|
|
|
|
|
Great control, small, simple, and yet does all it's supposed to do. Well, most of it anyway, that's where I want to ask you some questions.
1.First is that I implemented a mouseenter/mouseleave event to highlight the border with different color depending on whether the mouse is hovering above the control or not. However if I repeatedly move my mouse in and out of control at least three-four times a second I notice a lot of flickering at the drop down button. My guess is that when you do a WM_PAINT event you let the default wndproc to take over and then paint the custom border and dropdown button which causes the flickering. Is there any way to redraw this manually without base class? I tried it, but I'm very new at this whole GDI and window messages thing, so, not surprisingly I failed.
2.This is also related to mouseenter/mouseleave thing. You said that your combobox did not work with simple style. What did you mean by that, what exactly did not work? Because for some reason, and I don't know why I have problems when the style is set to dropdown instead of dropdownlist. The issue I have is that when I set the style to dropdown, sometimes, when I move the mouse quickly in or out of the control mouseenter/mouseleave events do not fire. So the border of the control does not change, it's really annoying. I tried catching wm_mouseleave message in the wndproc, but it seems it never gets sent. Any idea what's causing it?
I also posted a question about your datetimepicker control. Can you take a look at it too?
Thanks.
|
|
|
|
|
Thanks for your input.
I haven't looked at the control for a while, so it is a slow start for me as well. These are my answers to your questions:
1. Instead of doing the drawing in mouseenter and mouseleave, I suggest that you just set a bool flag in those function such as m_bMouseEntered = true in the mouseenter even tna m_bMouseEntered = false in the mouseleave event. Change the implementation of PaintFlatControlBorder so that it first test for if (m_bMouseEntered) then call ControlPaint.DrawBorder(g, rect, MyColor, ButtonBorderStyle.Solid);
2. ComboBox has 3 style, simple style looks like a normal List control. you can set that property and have a look at your winform for the difference. I don't think the dropdownlist and dropdown style would be different in dealing with those events.
|
|
|
|
|
first and foremost, good job!
second, I noticed that in WndProc you have:
IntPtr hDC = GetWindowDC(this.Handle);
Graphics gdc = Graphics.FromHdc(hDC);
however, only messages WM_NC_PAINT and WM_PAINT make use of them, while for any other message they're not used at all, therefore, my advice to you would be to limit their scope to just the observed messages. In any case I know you're cleaning up:
ReleaseDC(m.HWnd, hDC);
gdc.Dispose();
however, why create and dispose of resources, in this case, relatively expensive resources, that will not be used.
good luck
|
|
|
|
|
Thanks. I agree with your point. The code was structured that way was partially caused by my laziness and also trying to make the code as easy to read as possible. I did plan to build up a library of these controls, but I have stopped for a while due to some change in circumstances. Keep your suggestions coming and will benefit me and others
|
|
|
|
|
I have a Sony Vaio with 1900x1200 resolution.
This FlatCombobox works great, except there is an odd artifact:
Ther is a wide 3D gap showing between the Textbox portion of the control and the arrow part of the control.
Any ideas on this? I tried it as a C# dll and also with the VB.Net code snippet. They both do the same thing.
Elizabeth Gee
Information Architect - .Net Developer
http://www.nwtd.com
|
|
|
|
|
Liz,
Geez.. that is a very wide screen that you have! I haven't got the environment to try, but did you try my suggested code in other thread:
====================================================
When it come to adjusting for drawing, I tempt to use the graphic resolution, so say "g" is the Graphics object, I would do something like this:
int iWidth = (int) ((g.DpiX/96.0f) * DROPDOWNWIDTH);
I use 96 there because that is the pixel size for standard font display. I also make it a float so that we keep the precision when performing the math.
====================================================
See if that works for you.
Fadrian
|
|
|
|
|