FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Icon button

 
Post new topic   Reply to topic     Forum Index -> DFL
View previous topic :: View next topic  
Author Message
tim



Joined: 24 Jul 2005
Posts: 26

PostPosted: Tue Jul 26, 2005 7:03 am    Post subject: Icon button Reply with quote

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
Back to top
View user's profile Send private message
tim



Joined: 24 Jul 2005
Posts: 26

PostPosted: Tue Jul 26, 2005 7:08 am    Post subject: Reply with quote

Some screenshots:


Back to top
View user's profile Send private message
tim



Joined: 24 Jul 2005
Posts: 26

PostPosted: Tue Jul 26, 2005 7:10 am    Post subject: Reply with quote

EDITED: Usage of the ExtractIconEx and DrawIconEx function instead of ExtractIcon and DrawIcon resolved all icon size issues! So the button is now able to display both small icons and big icons, which can be toggled using the property.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic     Forum Index -> DFL All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group