📄 colordlg.c
字号:
/*
* COMMDLG - Color Dialog
*
* Copyright 1994 Martin Ayotte
* Copyright 1996 Albrecht Kleine
*
* 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 St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* BUGS : still seems to not refresh correctly
sometimes, especially when 2 instances of the
dialog are loaded at the same time */
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "commdlg.h"
#include "dlgs.h"
#include "wine/debug.h"
#include "cderr.h"
#include "cdlg.h"
WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
static INT_PTR CALLBACK ColorDlgProc( HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam );
#define CONV_LPARAMTOPOINT(lp,p) do { (p)->x = (short)LOWORD(lp); (p)->y = (short)HIWORD(lp); } while(0)
static const COLORREF predefcolors[6][8]=
{
{ 0x008080FFL, 0x0080FFFFL, 0x0080FF80L, 0x0080FF00L,
0x00FFFF80L, 0x00FF8000L, 0x00C080FFL, 0x00FF80FFL },
{ 0x000000FFL, 0x0000FFFFL, 0x0000FF80L, 0x0040FF00L,
0x00FFFF00L, 0x00C08000L, 0x00C08080L, 0x00FF00FFL },
{ 0x00404080L, 0x004080FFL, 0x0000FF00L, 0x00808000L,
0x00804000L, 0x00FF8080L, 0x00400080L, 0x008000FFL },
{ 0x00000080L, 0x000080FFL, 0x00008000L, 0x00408000L,
0x00FF0000L, 0x00A00000L, 0x00800080L, 0x00FF0080L },
{ 0x00000040L, 0x00004080L, 0x00004000L, 0x00404000L,
0x00800000L, 0x00400000L, 0x00400040L, 0x00800040L },
{ 0x00000000L, 0x00008080L, 0x00408080L, 0x00808080L,
0x00808040L, 0x00C0C0C0L, 0x00400040L, 0x00FFFFFFL },
};
static const WCHAR szColourDialogProp[] = {
'c','o','l','o','u','r','d','i','a','l','o','g','p','r','o','p',0 };
/* Chose Color PRIVATE Structure:
*
* This structure is duplicated in the 16 bit code with
* an extra member
*/
typedef struct CCPRIVATE
{
LPCHOOSECOLORW lpcc; /* points to public known data structure */
int nextuserdef; /* next free place in user defined color array */
HDC hdcMem; /* color graph used for BitBlt() */
HBITMAP hbmMem; /* color graph bitmap */
RECT fullsize; /* original dialog window size */
UINT msetrgb; /* # of SETRGBSTRING message (today not used) */
RECT old3angle; /* last position of l-marker */
RECT oldcross; /* last position of color/satuation marker */
BOOL updating; /* to prevent recursive WM_COMMAND/EN_UPDATE processing */
int h;
int s;
int l; /* for temporary storing of hue,sat,lum */
int capturedGraph; /* control mouse captured */
RECT focusRect; /* rectangle last focused item */
HWND hwndFocus; /* handle last focused item */
} CCPRIV, *LPCCPRIV;
/***********************************************************************
* CC_HSLtoRGB [internal]
*/
int CC_HSLtoRGB(char c, int hue, int sat, int lum)
{
int res = 0, maxrgb;
/* hue */
switch(c)
{
case 'R': if (hue > 80) hue -= 80; else hue += 160; break;
case 'G': if (hue > 160) hue -= 160; else hue += 80; break;
case 'B': break;
}
/* l below 120 */
maxrgb = (256 * min(120,lum)) / 120; /* 0 .. 256 */
if (hue < 80)
res = 0;
else
if (hue < 120)
{
res = (hue - 80) * maxrgb; /* 0...10240 */
res /= 40; /* 0...256 */
}
else
if (hue < 200)
res = maxrgb;
else
{
res= (240 - hue) * maxrgb;
res /= 40;
}
res = res - maxrgb / 2; /* -128...128 */
/* saturation */
res = maxrgb / 2 + (sat * res) / 240; /* 0..256 */
/* lum above 120 */
if (lum > 120 && res < 256)
res += ((lum - 120) * (256 - res)) / 120;
return min(res, 255);
}
/***********************************************************************
* CC_RGBtoHSL [internal]
*/
int CC_RGBtoHSL(char c, int r, int g, int b)
{
WORD maxi, mini, mmsum, mmdif, result = 0;
int iresult = 0;
maxi = max(r, b);
maxi = max(maxi, g);
mini = min(r, b);
mini = min(mini, g);
mmsum = maxi + mini;
mmdif = maxi - mini;
switch(c)
{
/* lum */
case 'L': mmsum *= 120; /* 0...61200=(255+255)*120 */
result = mmsum / 255; /* 0...240 */
break;
/* saturation */
case 'S': if (!mmsum)
result = 0;
else
if (!mini || maxi == 255)
result = 240;
else
{
result = mmdif * 240; /* 0...61200=255*240 */
result /= (mmsum > 255 ? mmsum = 510 - mmsum : mmsum); /* 0..255 */
}
break;
/* hue */
case 'H': if (!mmdif)
result = 160;
else
{
if (maxi == r)
{
iresult = 40 * (g - b); /* -10200 ... 10200 */
iresult /= (int) mmdif; /* -40 .. 40 */
if (iresult < 0)
iresult += 240; /* 0..40 and 200..240 */
}
else
if (maxi == g)
{
iresult = 40 * (b - r);
iresult /= (int) mmdif;
iresult += 80; /* 40 .. 120 */
}
else
if (maxi == b)
{
iresult = 40 * (r - g);
iresult /= (int) mmdif;
iresult += 160; /* 120 .. 200 */
}
result = iresult;
}
break;
}
return result; /* is this integer arithmetic precise enough ? */
}
/***********************************************************************
* CC_DrawCurrentFocusRect [internal]
*/
static void CC_DrawCurrentFocusRect( const CCPRIV *lpp )
{
if (lpp->hwndFocus)
{
HDC hdc = GetDC(lpp->hwndFocus);
DrawFocusRect(hdc, &lpp->focusRect);
ReleaseDC(lpp->hwndFocus, hdc);
}
}
/***********************************************************************
* CC_DrawFocusRect [internal]
*/
static void CC_DrawFocusRect( LPCCPRIV lpp, HWND hwnd, int x, int y, int rows, int cols)
{
RECT rect;
int dx, dy;
HDC hdc;
CC_DrawCurrentFocusRect(lpp); /* remove current focus rect */
/* calculate new rect */
GetClientRect(hwnd, &rect);
dx = (rect.right - rect.left) / cols;
dy = (rect.bottom - rect.top) / rows;
rect.left += (x * dx) - 2;
rect.top += (y * dy) - 2;
rect.right = rect.left + dx;
rect.bottom = rect.top + dy;
/* draw it */
hdc = GetDC(hwnd);
DrawFocusRect(hdc, &rect);
CopyRect(&lpp->focusRect, &rect);
lpp->hwndFocus = hwnd;
ReleaseDC(hwnd, hdc);
}
#define DISTANCE 4
/***********************************************************************
* CC_MouseCheckPredefColorArray [internal]
* returns 1 if one of the predefined colors is clicked
*/
static int CC_MouseCheckPredefColorArray( LPCCPRIV lpp, HWND hDlg, int dlgitem, int rows, int cols,
LPARAM lParam )
{
HWND hwnd;
POINT point;
RECT rect;
int dx, dy, x, y;
CONV_LPARAMTOPOINT(lParam, &point);
ClientToScreen(hDlg, &point);
hwnd = GetDlgItem(hDlg, dlgitem);
GetWindowRect(hwnd, &rect);
if (PtInRect(&rect, point))
{
dx = (rect.right - rect.left) / cols;
dy = (rect.bottom - rect.top) / rows;
ScreenToClient(hwnd, &point);
if (point.x % dx < ( dx - DISTANCE) && point.y % dy < ( dy - DISTANCE))
{
x = point.x / dx;
y = point.y / dy;
lpp->lpcc->rgbResult = predefcolors[y][x];
CC_DrawFocusRect(lpp, hwnd, x, y, rows, cols);
return 1;
}
}
return 0;
}
/***********************************************************************
* CC_MouseCheckUserColorArray [internal]
* return 1 if the user clicked a color
*/
static int CC_MouseCheckUserColorArray( LPCCPRIV lpp, HWND hDlg, int dlgitem, int rows, int cols,
LPARAM lParam )
{
HWND hwnd;
POINT point;
RECT rect;
int dx, dy, x, y;
COLORREF *crarr = lpp->lpcc->lpCustColors;
CONV_LPARAMTOPOINT(lParam, &point);
ClientToScreen(hDlg, &point);
hwnd = GetDlgItem(hDlg, dlgitem);
GetWindowRect(hwnd, &rect);
if (PtInRect(&rect, point))
{
dx = (rect.right - rect.left) / cols;
dy = (rect.bottom - rect.top) / rows;
ScreenToClient(hwnd, &point);
if (point.x % dx < (dx - DISTANCE) && point.y % dy < (dy - DISTANCE))
{
x = point.x / dx;
y = point.y / dy;
lpp->lpcc->rgbResult = crarr[x + (cols * y) ];
CC_DrawFocusRect(lpp, hwnd, x, y, rows, cols);
return 1;
}
}
return 0;
}
#define MAXVERT 240
#define MAXHORI 239
/* 240 ^...... ^^ 240
| . ||
SAT | . || LUM
| . ||
+-----> 239 ----
HUE
*/
/***********************************************************************
* CC_MouseCheckColorGraph [internal]
*/
static int CC_MouseCheckColorGraph( HWND hDlg, int dlgitem, int *hori, int *vert, LPARAM lParam )
{
HWND hwnd;
POINT point;
RECT rect;
long x,y;
CONV_LPARAMTOPOINT(lParam, &point);
ClientToScreen(hDlg, &point);
hwnd = GetDlgItem( hDlg, dlgitem );
GetWindowRect(hwnd, &rect);
if (PtInRect(&rect, point))
{
GetClientRect(hwnd, &rect);
ScreenToClient(hwnd, &point);
x = (long) point.x * MAXHORI;
x /= rect.right;
y = (long) (rect.bottom - point.y) * MAXVERT;
y /= rect.bottom;
if (hori)
*hori = x;
if (vert)
*vert = y;
return 1;
}
else
return 0;
}
/***********************************************************************
* CC_MouseCheckResultWindow [internal]
* test if double click one of the result colors
*/
int CC_MouseCheckResultWindow( HWND hDlg, LPARAM lParam )
{
HWND hwnd;
POINT point;
RECT rect;
CONV_LPARAMTOPOINT(lParam, &point);
ClientToScreen(hDlg, &point);
hwnd = GetDlgItem(hDlg, 0x2c5);
GetWindowRect(hwnd, &rect);
if (PtInRect(&rect, point))
{
PostMessageA(hDlg, WM_COMMAND, 0x2c9, 0);
return 1;
}
return 0;
}
/***********************************************************************
* CC_CheckDigitsInEdit [internal]
*/
int CC_CheckDigitsInEdit( HWND hwnd, int maxval )
{
int i, k, m, result, value;
long editpos;
char buffer[30];
GetWindowTextA(hwnd, buffer, sizeof(buffer));
m = strlen(buffer);
result = 0;
for (i = 0 ; i < m ; i++)
if (buffer[i] < '0' || buffer[i] > '9')
{
for (k = i + 1; k <= m; k++) /* delete bad character */
{
buffer[i] = buffer[k];
m--;
}
buffer[m] = 0;
result = 1;
}
value = atoi(buffer);
if (value > maxval) /* build a new string */
{
sprintf(buffer, "%d", maxval);
result = 2;
}
if (result)
{
editpos = SendMessageA(hwnd, EM_GETSEL, 0, 0);
SetWindowTextA(hwnd, buffer );
SendMessageA(hwnd, EM_SETSEL, 0, editpos);
}
return value;
}
/***********************************************************************
* CC_PaintSelectedColor [internal]
*/
void CC_PaintSelectedColor( HWND hDlg, COLORREF cr )
{
RECT rect;
HDC hdc;
HBRUSH hBrush;
HWND hwnd = GetDlgItem(hDlg, 0x2c5);
if (IsWindowVisible( GetDlgItem(hDlg, 0x2c6) )) /* if full size */
{
hdc = GetDC(hwnd);
GetClientRect(hwnd, &rect) ;
hBrush = CreateSolidBrush(cr);
if (hBrush)
{
hBrush = SelectObject(hdc, hBrush) ;
Rectangle(hdc, rect.left, rect.top, rect.right/2, rect.bottom);
DeleteObject ( SelectObject(hdc, hBrush) ) ;
hBrush = CreateSolidBrush( GetNearestColor(hdc, cr) );
if (hBrush)
{
hBrush = SelectObject(hdc, hBrush) ;
Rectangle(hdc, rect.right/2-1, rect.top, rect.right, rect.bottom);
DeleteObject(SelectObject(hdc, hBrush)) ;
}
}
ReleaseDC(hwnd, hdc);
}
}
/***********************************************************************
* CC_PaintTriangle [internal]
*/
void CC_PaintTriangle( HWND hDlg, int y)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -