mirror of https://github.com/roytam1/kmeleon.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
344 lines
8.5 KiB
344 lines
8.5 KiB
/* |
|
* Copyright (C) 2000 Brian Harris |
|
* |
|
* This program is free software; you can redistribute it and/or modify |
|
* it under the terms of the GNU General Public License as published by |
|
* the Free Software Foundation; either version 2, or (at your option) |
|
* any later version. |
|
* |
|
* This program 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 General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License |
|
* along with this program; if not, write to the Free Software |
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
*/ |
|
// adds icons to the menus |
|
// |
|
|
|
#include "stdafx.h" |
|
#include <tchar.h> |
|
#include <malloc.h> |
|
#include "Utils.h" |
|
|
|
#define PLUGIN_NAME "Bitmapped Menus" |
|
|
|
#pragma warning( disable : 4786 ) // C4786 bitches about the std::map template name expanding beyond 255 characters |
|
#include <map> |
|
#include <string> |
|
#include <vector> |
|
|
|
#define KMELEON_PLUGIN_EXPORTS |
|
#include "kmeleon_plugin.h" |
|
|
|
#define CONFIG_FILE _T("menuicons.cfg") |
|
|
|
//#define BMP_PADDING_LEFT 3 |
|
//#define BMP_PADDING_RIGHT 4 |
|
#define BMP_PADDING_LEFT 2 |
|
#define BMP_PADDING_RIGHT 2 |
|
|
|
int SPACE_BETWEEN = 0; // the space between the text and the accelerator, set to the width of 'X' |
|
//LONG MARGIN_LEFT = max(GetSystemMetrics(SM_CXMENUCHECK)+ BMP_PADDING_LEFT + BMP_PADDING_RIGHT, BMP_WIDTH + BMP_PADDING_LEFT + BMP_PADDING_RIGHT); |
|
#define MARGIN_RIGHT 16 |
|
|
|
int gBmpHeight = 16; |
|
int gBmpWidth = 16; |
|
int gMarginLeft = 16 + BMP_PADDING_LEFT + BMP_PADDING_RIGHT; |
|
|
|
typedef int (*DRAWBITMAPPROC)(DRAWITEMSTRUCT *dis); |
|
|
|
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); |
|
WNDPROC KMeleonWndProc; |
|
|
|
int Init(); |
|
void Create(HWND parent); |
|
void Config(HWND parent); |
|
void Quit(); |
|
void DoMenu(HMENU menu, char *param); |
|
//int GetConfigFiles(configFileType **configFiles); |
|
|
|
long DoMessage(const char *to, const char *from, const char *subject, long data1, long data2); |
|
|
|
kmeleonPlugin kPlugin = { |
|
KMEL_PLUGIN_VER, |
|
PLUGIN_NAME, |
|
DoMessage |
|
}; |
|
|
|
bool gbIsComCtl6 = false; |
|
|
|
/* |
|
# sample config |
|
|
|
filename1.bmp { |
|
ID_BLAH1 |
|
ID_BLAH2 |
|
ID_BLAH3 |
|
} |
|
filename2.bmp { |
|
ID_BLARG1 |
|
ID_BLARG2 |
|
} |
|
*/ |
|
|
|
BOOL bFirstRun; |
|
|
|
long DoMessage(const char *to, const char *from, const char *subject, long data1, long data2) |
|
{ |
|
if (to[0] == '*' || strcmp(to, kPlugin.dllname) == 0) { |
|
if (stricmp(subject, "Init") == 0) { |
|
Init(); |
|
} |
|
else if (strcmp(subject, "Create") == 0) { |
|
Create((HWND)data1); |
|
} |
|
else if (strcmp(subject, "Config") == 0) { |
|
Config((HWND)data1); |
|
} |
|
else if (strcmp(subject, "Quit") == 0) { |
|
Quit(); |
|
} |
|
else return 0; |
|
|
|
return 1; |
|
} |
|
return 0; |
|
} |
|
|
|
HBITMAP LoadImage24(const char* sFile, COLORREF* bgColor, int width = -1, int height = -1, int index = -1, int xstart = 0, int ystart = 0) |
|
{ |
|
if (!sFile || !*sFile) |
|
return 0; |
|
|
|
if (bgColor) *bgColor =-1; |
|
|
|
HDC hdcButton, hdcBitmap; |
|
HBITMAP hButton, hBitmap; |
|
HBRUSH hBrush; |
|
|
|
#ifdef _UNICODE |
|
wchar_t _sFile[MAX_PATH]; |
|
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, sFile, -1, _sFile, MAX_PATH); |
|
#else |
|
const char* _sFile = sFile; |
|
#endif |
|
UINT flag = LR_LOADFROMFILE | LR_CREATEDIBSECTION; |
|
|
|
if (strchr(sFile, '\\')) { |
|
hBitmap = (HBITMAP)LoadImage(NULL, _sFile, IMAGE_BITMAP, 0, 0, flag); |
|
} |
|
else { |
|
wchar_t fullpath[MAX_PATH]; |
|
kPlugin.kFuncs->FindSkinFile(_sFile, fullpath, MAX_PATH); |
|
hBitmap = (HBITMAP)LoadImage(NULL, fullpath, IMAGE_BITMAP, 0, 0, flag); |
|
} |
|
|
|
if (!hBitmap) return NULL; |
|
hdcBitmap = CreateCompatibleDC(NULL); |
|
|
|
struct { |
|
BITMAPINFOHEADER header; |
|
COLORREF col[256]; |
|
} bmpi = {0}; |
|
|
|
bmpi.header.biSize = sizeof(BITMAPINFOHEADER); |
|
|
|
int nCol = 0; |
|
int nLine = 0; |
|
GetDIBits(hdcBitmap, hBitmap, 0, 0, NULL, (BITMAPINFO*)&bmpi, DIB_RGB_COLORS); |
|
if (width != -1) { |
|
nCol = ((width*index) % bmpi.header.biWidth) / width; |
|
nLine = bmpi.header.biHeight / height - (width*index) / bmpi.header.biWidth - 1; |
|
} else { |
|
width = bmpi.header.biWidth; |
|
height = bmpi.header.biHeight; |
|
} |
|
|
|
|
|
if (bmpi.header.biBitCount == 32) { |
|
|
|
|
|
int srcWidth = bmpi.header.biWidth * 4; |
|
int srcHeight = bmpi.header.biHeight; |
|
|
|
int dstWidth = width * 4; |
|
int offset = nCol * dstWidth + nLine * srcWidth * height; |
|
|
|
if (offset + (height-1) * srcWidth + dstWidth > srcWidth * srcHeight) |
|
return NULL; |
|
|
|
BYTE* srcBits = new BYTE[srcWidth * srcHeight]; |
|
GetDIBits(hdcBitmap, hBitmap, 0, srcHeight, srcBits, (BITMAPINFO*)&bmpi, DIB_RGB_COLORS); |
|
|
|
bmpi.header.biWidth = width; |
|
bmpi.header.biHeight = height; |
|
|
|
BYTE* dstBits = NULL; |
|
HBITMAP hBmp = CreateDIBSection(hdcBitmap, (BITMAPINFO*)&bmpi, DIB_RGB_COLORS, (void**)&dstBits, NULL, 0); |
|
|
|
if (!hBmp) { |
|
DeleteObject(hBitmap); |
|
DeleteDC(hdcBitmap); |
|
delete[] srcBits; |
|
return NULL; |
|
} |
|
|
|
for (int i = 0; i< height; i++) |
|
memcpy(&dstBits[dstWidth*i], &srcBits[i * srcWidth + offset], dstWidth); |
|
|
|
DeleteObject(hBitmap); |
|
|
|
if (!gbIsComCtl6 && bgColor) { |
|
// Pseudo background color check |
|
*bgColor = RGB(255, 0, 255); |
|
for (int i=0;i<width*height*4;i+=4) |
|
if (dstBits[i] == 0) { |
|
*bgColor = RGB(dstBits[i+1], dstBits[i+2], dstBits[i+3]); |
|
break; |
|
} |
|
} |
|
|
|
delete[] srcBits; |
|
DeleteDC(hdcBitmap); |
|
return hBmp; |
|
} |
|
|
|
HGDIOBJ oldBmp = SelectObject(hdcBitmap, hBitmap); |
|
|
|
hdcButton = CreateCompatibleDC(hdcBitmap); |
|
hButton = CreateCompatibleBitmap(hdcBitmap, width, height); |
|
HGDIOBJ oldBmp2 = SelectObject(hdcButton, hButton); |
|
|
|
// fill the button with the transparency |
|
hBrush = CreateSolidBrush(RGB(255,0,255)); |
|
HGDIOBJ oldBrush = SelectObject(hdcButton, hBrush); |
|
PatBlt(hdcButton, 0, 0, width, height, PATCOPY); |
|
|
|
// copy the button from the full bitmap |
|
BitBlt(hdcButton, xstart, ystart, width, height, hdcBitmap, width*nCol + height*nLine, 0, SRCCOPY); |
|
SelectObject(hdcButton, oldBrush); |
|
SelectObject(hdcButton, oldBmp2); |
|
SelectObject(hdcBitmap, oldBmp); |
|
DeleteDC(hdcBitmap); |
|
DeleteDC(hdcButton); |
|
|
|
DeleteObject(hBrush); |
|
DeleteObject(hBitmap); |
|
|
|
if (bgColor) *bgColor = RGB(255,0,255); |
|
return hButton; |
|
} |
|
|
|
|
|
void ParseConfig(char *buffer) { |
|
BOOL currentBitmap = false; |
|
int index = 0; |
|
char* image = 0; |
|
char *p = strtok(buffer, "\n"); |
|
while (p != NULL) { |
|
|
|
// ignore the comments |
|
if (*p == '#') { |
|
p = strtok(NULL, "\n"); |
|
continue; |
|
} |
|
else if (!currentBitmap) { |
|
char *b = strchr(p, '{'); |
|
if (b) { |
|
*b = 0; |
|
TrimWhiteSpace(p); |
|
p = SkipWhiteSpace(p); |
|
image = strdup(p); |
|
currentBitmap = true; |
|
} |
|
} |
|
else { |
|
if ( strchr( p, '}' )) { |
|
currentBitmap = false; |
|
delete image; |
|
image = 0; |
|
index = 0; |
|
p = strtok(NULL, "\n"); |
|
continue; |
|
} |
|
|
|
TrimWhiteSpace(p); |
|
p = SkipWhiteSpace(p); |
|
|
|
RECT r = {index*gBmpWidth,0,(index+1)*gBmpWidth,gBmpHeight}; |
|
kPlugin.kFuncs->SetCmdIcon(p, image, &r, 0, 0, 0, 0); |
|
index++; |
|
} |
|
p = strtok(NULL, "\n"); |
|
} |
|
if (image) delete(image); |
|
} |
|
|
|
int Init() { |
|
bFirstRun = TRUE; |
|
|
|
HMODULE hComCtlDll = LoadLibrary(_T("comctl32.dll")); |
|
if (hComCtlDll) |
|
{ |
|
typedef HRESULT (CALLBACK *PFNDLLGETVERSION)(DLLVERSIONINFO*); |
|
|
|
PFNDLLGETVERSION pfnDllGetVersion = (PFNDLLGETVERSION)GetProcAddress(hComCtlDll, "DllGetVersion"); |
|
|
|
if (pfnDllGetVersion) |
|
{ |
|
DLLVERSIONINFO dvi = {0}; |
|
dvi.cbSize = sizeof(dvi); |
|
|
|
HRESULT hRes = (*pfnDllGetVersion)(&dvi); |
|
if (SUCCEEDED(hRes) && dvi.dwMajorVersion >= 6) |
|
gbIsComCtl6 = TRUE; |
|
} |
|
|
|
FreeLibrary(hComCtlDll); |
|
} |
|
|
|
TCHAR cfgPath[MAX_PATH]; |
|
kPlugin.kFuncs->FindSkinFile(CONFIG_FILE, cfgPath, MAX_PATH); |
|
|
|
FILE *cfgFile = _tfopen(cfgPath, _T("r")); |
|
if (cfgFile){ |
|
long cfgFileSize = FileSize(cfgFile); |
|
|
|
char *cfgFileBuffer = new char[cfgFileSize+1]; |
|
if (cfgFileBuffer) { |
|
fread(cfgFileBuffer, sizeof(char), cfgFileSize, cfgFile); |
|
cfgFileBuffer[cfgFileSize] = 0; |
|
ParseConfig(cfgFileBuffer); |
|
|
|
delete [] cfgFileBuffer; |
|
} |
|
fclose(cfgFile); |
|
} |
|
return true; |
|
} |
|
|
|
void Create(HWND parent){ |
|
bFirstRun=FALSE; |
|
} |
|
|
|
void Config(HWND parent) |
|
{ |
|
TCHAR cfgPath[MAX_PATH]; |
|
kPlugin.kFuncs->FindSkinFile(CONFIG_FILE, cfgPath, MAX_PATH); |
|
ShellExecute(parent, NULL, _T("notepad.exe"), cfgPath, NULL, SW_SHOW); |
|
} |
|
|
|
void Quit(){ |
|
} |
|
|
|
// so it doesn't munge the function name |
|
extern "C" { |
|
|
|
KMELEON_PLUGIN kmeleonPlugin *GetKmeleonPlugin() { |
|
return &kPlugin; |
|
} |
|
|
|
}
|
|
|