|
You'll need to set the DrawMode property[^] to OwnerDrawFixed or OwnerDrawVariable , depending on whether or not your items have a fixed height.
For OwnerDrawVariable , you'll need to handle the MeasureItem event[^] to specify the size for each item.
You'll then need to handle the DrawItem event[^] to draw each item in the ComboBox . You should be able to identify whether the item is the edit portion of the ComboBox by checking for the DrawItemState.ComboBoxEdit flag in the State property[^] of the DrawItemEventArgs [^].
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Bloody hell, that deserves an up vote just for knowing all the bits!
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
The ComboBox contains plain text so I set DrawMode to OwnerDrawFixed. As far as I understand, the following should work, but it doesn't:
private void comboBox_DrawItem(Object sender, DrawItemEventArgs e)
{
if (e.Index < 0)
{
return;
}
if (e.State == DrawItemState.ComboBoxEdit)
{
e.Graphics.FillRectangle(new SolidBrush(Color.Violet), e.Bounds);
}
else
{
e.Graphics.FillRectangle(new SolidBrush(((ComboBox)sender).BackColor), e.Bounds);
}
e.Graphics.DrawString(((ComboBox)sender).Items[e.Index].ToString(), e.Font,
new SolidBrush(((ComboBox)sender).ForeColor),
new Point(e.Bounds.X, e.Bounds.Y));
e.DrawFocusRectangle();
}
What am I missing?
|
|
|
|
|
It only seem to work if the DropDownStyle is set to DropDownList ; I don't think you can owner-draw the edit box of an editable ComboBox .
The State property can combine multiple values, so you can't do a straight equality test. You'll need to use the HasFlag method[^] instead.
Your code also won't draw anything until you select an item from the list. If you want to see the custom background colour even when you haven't selected an item, you'll need to remove the initial e.Index test, and add a conditional test around the DrawString line:
private void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
{
var control = (ComboBox)sender;
if (e.State.HasFlag(DrawItemState.ComboBoxEdit))
{
e.Graphics.FillRectangle(Brushes.Violet, e.Bounds);
}
else
{
e.DrawBackground();
}
if (e.Index >= 0)
{
e.Graphics.DrawString(control.Items[e.Index].ToString(), e.Font,
new SolidBrush(e.ForeColor), e.Bounds.X, e.Bounds.Y);
}
e.DrawFocusRectangle();
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
e.State.HasFlag gave a compile error so I changed it to:
if (0 < (((int)e.State) & ((int)DrawItemState.ComboBoxEdit)))
There is one strange issue left, though. When I select an item in the ComboBox, the color of the text becomes white. When the ComboBox looses focus, the text becomes black again.
|
|
|
|
|
HasFlag was added in .NET 4.0, so I guess you must be using 3.5 or earlier.
The ForeColor property will change depending on whether or not the item is highlighted. If you always want the text to be black, then use Brushes.Black instead.
private void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
{
var control = (ComboBox)sender;
if (0 != (e.State & DrawItemState.ComboBoxEdit))
{
e.Graphics.FillRectangle(Brushes.Violet, e.Bounds);
if (e.Index >= 0)
{
e.Graphics.DrawString(control.Items[e.Index].ToString(), e.Font,
Brushes.Black, e.Bounds.X, e.Bounds.Y);
}
}
else
{
e.DrawBackground();
if (e.Index >= 0)
{
e.Graphics.DrawString(control.Items[e.Index].ToString(), e.Font,
new SolidBrush(e.ForeColor), e.Bounds.X, e.Bounds.Y);
}
}
e.DrawFocusRectangle();
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Many thanks, it works perfectly now!
|
|
|
|
|
I have a standard ComboBox. As soon as the user "touches" (with the mouse or the keyboard) the ComboBox, I would like to enforce that SelectedValue is never again -1. The normal case is that if the user doesn't select an item, SelectedValue becomes -1. However, if the user doesn't make a selection, I would like the first item to be selected. How can I accomplish this?
|
|
|
|
|
The easiest way is to change the DropDownStyle to DropDownList - then once a value is selected it can never be deselected.
If you combine that with handling the DropDown event and setting the SelectedIndex to zero in that, it should do what you want.
Those who fail to learn history are doomed to repeat it. --- George Santayana (December 16, 1863 – September 26, 1952)
Those who fail to clear history are doomed to explain it. --- OriginalGriff (February 24, 1959 – ∞)
|
|
|
|
|
DropDownStyle is already set to DropDownList. If the user doesn't select any of the items (he/she clicks outside the ComboBox after he/she has "touched" ComboBox) then I don't get ComboBox_SelectedIndexChanged or ComboBox_SelectionChangeCommitted events. It seems those events are only fired when a selection is made inside the ComboBox.
|
|
|
|
|
That's why I said "If you combine that with handling the DropDown event..."
Those who fail to learn history are doomed to repeat it. --- George Santayana (December 16, 1863 – September 26, 1952)
Those who fail to clear history are doomed to explain it. --- OriginalGriff (February 24, 1959 – ∞)
|
|
|
|
|
Ok, I understand:
private void comboBox_DropDown(object sender, EventArgs e)
{
if (((ComboBox)sender).SelectedIndex < 0)
{
((ComboBox)sender).SelectedIndex = 0;
}
}
Very good idea, that works great! Thanks!
|
|
|
|
|
That's the event!
You're welcome!
Those who fail to learn history are doomed to repeat it. --- George Santayana (December 16, 1863 – September 26, 1952)
Those who fail to clear history are doomed to explain it. --- OriginalGriff (February 24, 1959 – ∞)
|
|
|
|
|
i have created a dll file that include user control with panel on it ,when i add this dll to my tool box i can only have access to user control and not the panel ! while i need to drag n drop a picture box into it ! plz help me on this .
i just want to do it on design time not programitically!
|
|
|
|
|
Start here[^].
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
I have been trying to start multiple instances of iexplore and other
apps then get the handle so i can reposition it and other actions.
It works great in Windows 7 using myProcess.Id to find the process and retrieve the MainWindowHandle. It also works in Windows 8.1 if there is
only 1 instance of the application running.
The Problem: When i get more than one instance of the app open in W8.1 I can not find the handle. I can get the process id but can't get the handle even by looping through all processes and looking for the handle.
Help
|
|
|
|
|
RRLCoder wrote: I can get the process id but can't get the handle Can you post a SMALL examle that reproduces this problem?
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
This is a bit long but shows most of what i've tried
string ProcToStart = "iexplore";
int saveProcId;
Process myProcess = new Process();
myProcess.StartInfo.FileName = TargetFile;
myProcess.StartInfo.Arguments = TargetArguments;
myProcess.StartInfo.UseShellExecute = true;
myProcess.Start();
saveProcId = myProcess.Id;
1-the simple approach, just trying to access myProcess.MainWindowHandle gets 0 even after a 10 min sleep
2--here is one method looping through all processes
I also tried this wraped in: while (proc.MainWindowHandle == IntPtr.Zero) (ran forever & didnt find a hit)....
foreach (Process proc in Process.GetProcesses())
{
if (proc.Id == saveProcId)
{
Console.WriteLine(" PID: " + proc.Id + " Handle: " + proc.MainWindowHandle);
}
}
3--Here is another attempt using ....GetProcessById
try
{
ChosenProc = Process.GetProcessById(ProcId);
Console.WriteLine("Your Process Info: " );
Console.WriteLine(" Id: " + ChosenProc.Id
+ " Handle: " + ChosenProc.Handle
+ " MainWinHndl: " + ChosenProc.MainWindowHandle
+ " Name: " + ChosenProc.ProcessName);
return true;
}
catch
{
ChosenProc = null;
Console.WriteLine("Incorrect entry.");
return false;
}
|
|
|
|
|
RRLCoder wrote: This is a bit long but shows most of what i've tried InvalidOperationException? Try using the full path to the application;
Process myProcess = new Process();
myProcess.StartInfo.FileName = @"C:\Program Files\Internet Explorer\iexplore.exe";
myProcess.StartInfo.Arguments = @"http://www.codeproject.com";
myProcess.Start();
Console.WriteLine(myProcess.Id);
Console.ReadLine();
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Thanks...
I just tried it both ways (fully qualified and just the iexplore) followed by:
Console.WriteLine("IE Instance started... PID= " + myProc.Id + myProc.MainWindowHandle);
I get an unhandled exception on the myProcess.MainWindowHandle no matter how much of a sleep or if i loop looking for the process id. Again, it works find if there is only 1 instance of the target app (iexplor in this case) open.
|
|
|
|
|
I run an indoor sports facility.
Our receptionist uses some media player for background music in our foyer.
What I need is a way to mute that media player, to play my own .wav file to remind players to be ready 10 minutes before events start, (triggered by system time) then resume the background media player.
If that makes sense?
My application is in C# and uses AXVLC.
Im also considering making it a Service instead, so the receptionist doesnt close it.
|
|
|
|
|
Uhm what is your question, does it make sense, yes. There aeems to be plenty of support for this process on Google.
I would not make it a service, what happens if you want to interrupt the announcement or make an adhoc announcement. You actually need a PA system and should probably look around for a package before attempting to build your own (this assumes you are into running the sports centre and are not a developer).
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
I've been a hobbyist developer for much longer than I've been working at the centre. But theyve just made me a manager, so now looking at making some cool new toys. We've got a PA system, but I want to make things as automated as possible as Im getting busy doing other things.
|
|
|
|
|
el_stupey wrote: Im also considering making it a Service instead, so the receptionist doesnt close it. That's not what a service is for; and yes, the user can close services. Using services also introduces a new problem - they usually run under a system-account, and should not be messing with the users' desk.
Simplest solution; get a list of MP3's to play. Play them yourself (from code), then it becomes quite easy to interrupt the song at a predefined time and to play "something else".
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Maybe a service isnt what I need. Was just a thought.
Thanks for the suggestion, I might try that out.
Also found another answer here. Only problem with that is it claims win7 and later which means finally upgrade from vista.
|
|
|
|