tim
Joined: 24 Jul 2005 Posts: 26
|
Posted: Tue Jul 26, 2005 7:03 am Post subject: Icon button |
|
|
UPDATED:
I developed an icon button - a button that displays an icon on the left and a label on the right. It automatically centers them, moves them by a small offset when the button is pressed / depressed etc. It also allows you to retrieve the minimum width and height, so you can easily use it in a programmatically controlled layout.
Its main properties/functions:
* click
* loadIcon(char[] path)
* text
* minimumHeight
* minimumWidth
* extractSmall - if set to true, extracts the small icon (16x16), otherwise the big icon (32x32)
Really simple stuff, but I once again learned a thing or two about the Win32 API. Here is the source code - including a demo app (you must link with Shell32.lib):
Code: |
// main.d
import dfl.all;
import dflext.imagebutton;
import dfl.winapi;
import std.c.windows.windows;
class MainForm: Form
{
IconButton button;
this()
{
super();
setBounds(left, top, 128, 100);
button = new IconButton;
button.parent = this;
button.extractSmall = true;
button.loadIcon("ie.ico");
button.text = "Launch IE";
button.click ~= &clickHandler;
layoutChildren();
resizeRedraw(true);
}
void clickHandler(Object obj, EventArgs args)
{
printf("Click!\n");
}
void layoutChildren()
{
const int space = 5;
button.setBounds(space,
space,
clientSize.width - 2 * space,
clientSize.height - 2 * space);
}
protected void onResize(EventArgs args)
{
super.onResize(args);
layoutChildren();
}
}
int main()
{
Application.run(new MainForm);
return 0;
}
// autolabel.d
module dflext.autolabel;
import dfl.winapi;
import dfl.all;
import std.string;
class AutoLabel: Label
{
void text(char[] value)
{
if(value != Label.text) {
Label.text = value;
SIZE size;
HDC dc = GetDC(handle);
SelectObject(dc, font.handle);
Graphics g = new Graphics(dc);
GetTextExtentPoint32A(g.handle, toStringz(value), value.length, &size);
g.dispose();
ReleaseDC(handle, dc);
setBounds(left, top, size.cx, size.cy);
}
}
char[] text()
{
return Label.text;
}
}
// iconbox.d
module dflext.iconbox;
import dfl.all;
import dfl.winapi;
import std.string;
const int DI_NORMAL = 3;
extern(Windows)
{
HICON ExtractIconExA(LPCSTR, int, HICON *, HICON *, UINT);
}
class IconBox: Control
{
Icon m_icon;
bool m_extractSmall = true;
public bool extractSmall()
{
return m_extractSmall;
}
public void extractSmall(bool value)
{
m_extractSmall = value;
}
protected void onPaint(PaintEventArgs args)
{
if(m_icon is null)
return;
DrawIconEx(args.graphics.handle,
0,
0,
m_icon.handle,
m_icon.width,
m_icon.height,
cast(uint)0,
cast(HANDLE)0,
cast(uint)DI_NORMAL);
}
public void loadIcon(char[] path)
{
HICON hIcon;
if(m_extractSmall)
ExtractIconExA(toStringz(path), 0, cast(HICON*)0, &hIcon, cast(uint)1);
else
ExtractIconExA(toStringz(path), 0, &hIcon, cast(HICON*)0, cast(uint)1);
m_icon = new Icon(hIcon);
setBounds(left, top, m_icon.width, m_icon.height);
}
}
// iconbutton.d
module dflext.imagebutton;
import dflext.autolabel;
import dflext.iconbox;
import dfl.all;
import std.random;
const int DFC_BUTTON = 4;
const int DFCS_PUSHED = 512;
const int DFCS_BUTTONPUSH = 16;
extern(Windows)
{
BOOL DrawFrameControl(HDC, LPRECT, UINT, UINT);
}
class IconButton: Control
{
AutoLabel m_label;
IconBox m_iconBox;
bool m_pushed;
const int OFFSET = 2;
const int SPACE = 5;
public bool extractSmall()
{
return m_iconBox.extractSmall;
}
public void extractSmall(bool value)
{
m_iconBox.extractSmall = value;
}
protected void onClick(EventArgs args)
{
}
public int minimumHeight()
{
return m_iconBox.height > m_label.height ? m_iconBox.height : m_label.height;
}
public int minimumWidth()
{
return SPACE + m_iconBox.width + SPACE + m_label.width + SPACE;
}
void paintFrame(HDC dc)
{
RECT rect;
getClientRect(rect);
int style = DFCS_BUTTONPUSH;
if(m_pushed)
style |= DFCS_PUSHED;
DrawFrameControl(dc,
&rect,
DFC_BUTTON,
style);
}
private void mouseDownHandler(Object obj, MouseEventArgs args)
{
onMouseDown(args);
}
private void mouseUpHandler(Object obj, MouseEventArgs args)
{
onMouseUp(args);
}
private void getClientRect(out RECT rect)
{
rect.left = 0;
rect.top = 0;
rect.bottom = height;
rect.right = width;
}
void onPaint(PaintEventArgs args)
{
paintFrame(args.graphics.handle);
}
private void moveByOffset(Control control, int offset)
{
control.setBounds(control.left + offset,
control.top + offset,
control.width,
control.height);
}
protected void onMouseDown(MouseEventArgs args)
{
m_pushed = true;
moveByOffset(m_label, OFFSET);
moveByOffset(m_iconBox, OFFSET);
invalidateAll();
}
protected void invalidateAll()
{
RECT rect;
getClientRect(rect);
InvalidateRect(handle,
&rect,
TRUE);
}
protected void onMouseUp(MouseEventArgs args)
{
m_pushed = false;
moveByOffset(m_label, -OFFSET);
moveByOffset(m_iconBox, -OFFSET);
invalidateAll();
click(this, new EventArgs);
}
this()
{
//setStyle(ControlStyles.RESIZE_REDRAW, true);
m_iconBox = new IconBox;
m_iconBox.mouseDown ~= &mouseDownHandler;
m_iconBox.mouseUp ~= &mouseUpHandler;
m_iconBox.parent = this;
m_label = new AutoLabel;
m_label.mouseDown ~= &mouseDownHandler;
m_label.mouseUp ~= &mouseUpHandler;
m_label.parent = this;
}
protected void onResize(EventArgs args)
{
layoutChildren();
super.onResize(args);
}
void backColor(Color value)
{
super.backColor = value;
m_label.backColor = value;
}
Color backColor()
{
return super.backColor();
}
void layoutChildren()
{
int totalW = m_iconBox.width + SPACE + m_label.width;
m_iconBox.setBounds(width / 2 - totalW / 2,
height / 2 - m_iconBox.height / 2,
m_iconBox.width,
m_iconBox.height);
m_label.setBounds(m_iconBox.left + m_iconBox.width + SPACE,
height / 2 - m_label.height / 2,
m_label.width, m_label.height);
}
public void text(char[] value)
{
if(value != m_label.text) {
m_label.text = value;
layoutChildren();
}
}
public char[] text()
{
return m_label.text;
}
public void loadIcon(char[] path)
{
m_iconBox.loadIcon(path);
layoutChildren();
}
}
|
Last edited by tim on Tue Jul 26, 2005 8:55 am; edited 2 times in total |
|