private void OnListBoxDrawItem(object sender, DrawItemEventArgs e)
{
// We cannot do anything with an invalid index
if (e.Index < 0)
return;
// Update our content object with values from the list item
UpdateContentFromItemIndex(e.Index);
// By default the button is in the normal state
PaletteState buttonState = PaletteState.Normal;
// Is this item disabled
if ((e.State & DrawItemState.Disabled) == DrawItemState.Disabled)
buttonState = PaletteState.Disabled;
else
{
// Is the mouse over the item about to be drawn
bool mouseOver = (e.Index >= 0) && (e.Index == _listBox.MouseIndex);
// If selected then show as a checked item
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
if (SelectionMode == CheckedSelectionMode.None)
_drawButton.Checked = false;
else
{
_drawButton.Checked = true;
buttonState = (mouseOver ? PaletteState.CheckedTracking : PaletteState.CheckedNormal);
}
}
else
{
_drawButton.Checked = false;
if (mouseOver && (SelectionMode != CheckedSelectionMode.None))
buttonState = PaletteState.Tracking;
}
// Do we need to show item as having the focus
bool hasFocus = false;
if (((e.State & DrawItemState.Focus) == DrawItemState.Focus) &&
((e.State & DrawItemState.NoFocusRect) != DrawItemState.NoFocusRect))
hasFocus = true;
_overrideNormal.Apply = hasFocus;
_overrideTracking.Apply = hasFocus;
_overridePressed.Apply = hasFocus;
_overrideCheckedTracking.Apply = hasFocus;
_overrideCheckedNormal.Apply = hasFocus;
_overrideCheckedPressed.Apply = hasFocus;
}
// Update the view with the calculated state
_drawButton.ElementState = buttonState;
// Update check box to show correct checked image
_drawCheckBox.CheckState = GetItemCheckState(e.Index);
// Grab the raw device context for the graphics instance
IntPtr hdc = e.Graphics.GetHdc();
try
{
// Create bitmap that all drawing occurs onto, then we can blit it later to remove flicker
IntPtr hBitmap = PI.CreateCompatibleBitmap(hdc, e.Bounds.Right, e.Bounds.Bottom);
// If we managed to get a compatible bitmap
if (hBitmap != IntPtr.Zero)
{
try
{
// Must use the screen device context for the bitmap when drawing into the
// bitmap otherwise the Opacity and RightToLeftLayout will not work correctly.
PI.SelectObject(_screenDC, hBitmap);
// Easier to draw using a graphics instance than a DC!
using (Graphics g = Graphics.FromHdc(_screenDC))
{
// Ask the view element to layout in given space, needs this before a render call
using (ViewLayoutContext context = new ViewLayoutContext(this, Renderer))
{
context.DisplayRectangle = e.Bounds;
_listBox.ViewDrawPanel.Layout(context);
_layoutDocker.Layout(context);
}
// Ask the view element to actually draw
using (RenderContext context = new RenderContext(this, g, e.Bounds, Renderer))
{
_listBox.ViewDrawPanel.Render(context);
_layoutDocker.Render(context);
}
// Now blit from the bitmap from the screen to the real dc
PI.BitBlt(hdc, e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height, _screenDC, e.Bounds.X, e.Bounds.Y, PI.SRCCOPY);
}
}
finally
{
// Delete the temporary bitmap
PI.DeleteObject(hBitmap);
}
}
}
finally
{
// Must reserve the GetHdc() call before
e.Graphics.ReleaseHdc();
}
}