/******************************************************************************
* A Skinned Button Win32 Implementation
* Copyright (C) 2007 Paolo Medici (www.pmx.it)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*******************************************************************************/
/** @file skin_button.cpp
* A Skinned Button Win32 Implementation
*
* Bitmap should composed by two pieces [top: release, bottom: pressed]
*
* @author Paolo Medici (C)2007
*
* @license LGPL
**/
#include <windowsx.h>
#include "skin_button.h"
/// Two state
#define BMS_RELEASED 0
#define BMS_PRESSED 1
/// The classname
const char szSkinButtonClassName[]="pmclass32_skinbutton";
/// callback WM_PAINT
static void Widget_OnPaint(HWND hwnd)
{
HBITMAP hbmp = (HBITMAP) GetWindowLong(hwnd,0);
LONG State = (LONG) GetWindowLong(hwnd,4);
BITMAP bm;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmOld = (HBITMAP) SelectObject(hdcMem, hbmp);
int h;
GetObject(hbmp, sizeof(bm), &bm);
h = bm.bmHeight/2;
BitBlt(hdc, 0, 0, bm.bmWidth, h, hdcMem, 0, State * h, SRCCOPY);
SelectObject(hdcMem, hbmOld);
DeleteDC(hdcMem);
EndPaint(hwnd, &ps);
}
/// callback WM_DESTROY
static void Widget_OnDestroy(HWND hwnd) { }
/// callback WM_CREATE
static BOOL Widget_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct)
{
SetWindowLong(hwnd, GWL_ID, (LONG) lpCreateStruct->hMenu);
SetWindowLong(hwnd,0, (LONG) lpCreateStruct->lpCreateParams);
SetWindowLong(hwnd,4, BMS_RELEASED);
return TRUE;
}
/// callback WM_LBUTTONDWON
static void Widget_OnLButtonDown(HWND hwnd, BOOL fDoubleClick, int x,
int y, UINT keyFlags)
{
SetCapture(hwnd);
SetWindowLong(hwnd,4,BMS_PRESSED);
InvalidateRect(hwnd, NULL, TRUE);
}
/// callback WM_LBUTTONUP
static void Widget_OnLButtonUp(HWND hwnd, int x, int y, UINT keyFlags)
{
HBITMAP hbmp = (HBITMAP) GetWindowLong(hwnd,0);
BITMAP bm;
ReleaseCapture();
GetObject(hbmp, sizeof(bm), &bm);
SetWindowLong(hwnd,4,BMS_RELEASED);
int h = bm.bmHeight/2;
if((x>=0)&&(x<bm.bmWidth)&&(y>=0)&&(y<h))
SendMessage(GetParent(hwnd), WM_COMMAND, (WPARAM) GetWindowLong(hwnd, GWL_ID), (LPARAM) hwnd);
InvalidateRect(hwnd, NULL, TRUE);
}
/// Callback proc
LRESULT CALLBACK SkinButtonProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch (Message) /* handle the messages */
{
HANDLE_MSG(hwnd, WM_CREATE, Widget_OnCreate );
HANDLE_MSG(hwnd, WM_DESTROY, Widget_OnDestroy );
HANDLE_MSG(hwnd, WM_PAINT, Widget_OnPaint );
HANDLE_MSG(hwnd, WM_LBUTTONDOWN, Widget_OnLButtonDown);
HANDLE_MSG(hwnd, WM_LBUTTONUP, Widget_OnLButtonUp);
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, Message, wParam, lParam);
}
return 0;
}
/// Register This class
int Register_Skin_Button(HINSTANCE hThisInstance )
{
WNDCLASSEX wincl; /* Data structure for the windowclass */
/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szSkinButtonClassName;
wincl.lpfnWndProc = SkinButtonProc; /* This function is called by windows */
wincl.style = 0; /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);
/* Use default icon and mouse-pointer */
wincl.hIcon = NULL;
wincl.hIconSm = NULL;
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* No menu */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 2*sizeof(DWORD); /* structure or the window instance */
/* Use Windows's default color as the background of the window */
wincl.hbrBackground = NULL;
/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
return 0;
return 1;
}
/// helper function to add to window the Skin Button class
HWND AddSkinButton(HWND hwnd, int x, int y, UINT idc, HINSTANCE hInst, HBITMAP hbmp)
{
BITMAP bm;
GetObject(hbmp, sizeof(bm), &bm);
return CreateWindow(
szSkinButtonClassName, /* Classname */
"", /* Title Text */
WS_CHILD | WS_VISIBLE, /* default window */
x, /* Windows decides the position */
y, /* where the window ends up on the screen */
bm.bmWidth,
bm.bmHeight/2,
hwnd,
(HMENU) idc,
hInst, /* Program Instance handler */
hbmp
);
}