📄 wingdi.c
字号:
/*
* Copyright (c) 1999, 2000, 2001 Greg Haerr <greg@censoft.com>
*
* Win32 API upper level graphics drawing routines
*/
#include "windows.h"
#include "wintern.h"
#include "device.h"
#include <stdlib.h>
#include <string.h>
#define MAXSYSCOLORS 29 /* # of COLOR_* system colors*/
#define MAXSTOCKOBJECTS 18 /* # of stock objects*/
#if ERASEMOVE
BOOL mwERASEMOVE = TRUE; /* default XORMOVE repaint algorithm*/
#else
BOOL mwERASEMOVE = FALSE; /* default ERASEMOVE repaint algorithm*/
#endif
/* cast a pointer to an integer*/
#if DOS_TURBOC
#define PTRTOINT unsigned long
#else
#define PTRTOINT unsigned int
#endif
static HDC cliphdc; /* current window cliprects*/
/* default bitmap for new DCs*/
static MWBITMAPOBJ default_bitmap = {
{OBJ_BITMAP, TRUE}, 1, 1, 1, 1, 1, 1
};
static BOOL MwExtTextOut(HDC hdc, int x, int y, UINT fuOptions,
CONST RECT *lprc, LPCVOID lpszString, UINT cbCount,
CONST INT *lpDx, int flags);
static int MwDrawText(HDC hdc, LPCVOID lpString, int nCount, LPRECT lpRect,
UINT uFormat, int flags);
HDC WINAPI
GetDCEx(HWND hwnd,HRGN hrgnClip,DWORD flags)
{
HDC hdc;
if(!hwnd) /* handle NULL hwnd => desktop*/
hwnd = rootwp;
/* handle private DC's*/
if(hwnd->owndc && !(flags & DCX_WINDOW))
return hwnd->owndc;
/* add caching?*/
hdc = GdItemNew(struct hdc);
if(!hdc)
return NULL;
hdc->psd = &scrdev;
hdc->hwnd = hwnd;
if(flags & DCX_DEFAULTCLIP) {
flags &= ~DCX_DEFAULTCLIP;
if(hwnd->style & WS_CLIPSIBLINGS)
flags |= DCX_CLIPSIBLINGS;
if(hwnd->style & WS_CLIPCHILDREN)
flags |= DCX_CLIPCHILDREN;
}
hdc->flags = flags;
hdc->bkmode = OPAQUE;
hdc->textalign = TA_LEFT | TA_TOP | TA_NOUPDATECP;
hdc->bkcolor = RGB(255, 255, 255); /* WHITE*/
hdc->textcolor = RGB(0, 0, 0); /* BLACK*/
hdc->brush = (MWBRUSHOBJ *)GetStockObject(WHITE_BRUSH);
hdc->pen = (MWPENOBJ *)GetStockObject(BLACK_PEN);
hdc->font = (MWFONTOBJ *)GetStockObject(SYSTEM_FONT);
#if UPDATEREGIONS
if(hrgnClip) {
/* make a copy of passed region*/
hdc->region = (MWRGNOBJ *)CreateRectRgn(0, 0, 0, 0);
CombineRgn((HRGN)hdc->region, hrgnClip, NULL, RGN_COPY);
}
#endif
/* make default bitmap compatible with scrdev
* otherwise problems occur later because selecting
* in the default bitmap overwrite planes and bpp
* in a memory dc, and thus it becomes incompatible
* with scrdev.
*/
default_bitmap.planes = scrdev.planes;
default_bitmap.bpp = scrdev.bpp;
hdc->bitmap = &default_bitmap;
hdc->drawmode = R2_COPYPEN;
hdc->pt.x = 0;
hdc->pt.y = 0;
/* assign private DC if CS_OWNDC and not WindowDC*/
if((hwnd->pClass->style & CS_OWNDC) && !(flags & DCX_WINDOW)) {
/* must exclude update region due to BeginPaint GetDCEx call*/
hdc->flags |= DCX_EXCLUDEUPDATE;
hwnd->owndc = hdc;
}
return hdc;
}
HDC WINAPI
GetDC(HWND hwnd)
{
/*
* Exclude update regions when drawing with GetDC.
* This is required because some programs use GetDC
* when painting outside of BeginPaint/EndPaint, and
* the update region is empty then.
*/
return GetDCEx(hwnd, NULL, DCX_DEFAULTCLIP|DCX_EXCLUDEUPDATE);
}
HDC WINAPI
GetWindowDC(HWND hwnd)
{
/*
* Exclude update region for now, since we
* don't keep track of non-client update regions yet
*/
return GetDCEx(hwnd, NULL,DCX_WINDOW|DCX_DEFAULTCLIP|DCX_EXCLUDEUPDATE);
}
/* free a DC allocated from GetDC*/
int WINAPI
ReleaseDC(HWND hwnd, HDC hdc)
{
/* don't delete a memory dc on release*/
if(!hdc || (hdc->psd->flags&PSF_MEMORY))
return 0;
if(hdc == cliphdc)
cliphdc = NULL;
/* handle private DC's*/
if(hdc->hwnd->owndc && !(hdc->flags & DCX_WINDOW))
return 1;
DeleteObject((HBRUSH)hdc->brush);
DeleteObject((HPEN)hdc->pen);
#if 0 /* don't delete font resources on ReleaseDC... use DeleteObject instead*/
DeleteObject((HFONT)hdc->font);
#endif
DeleteObject((HRGN)hdc->region);
/*
* We can only select a bitmap in a memory DC,
* so bitmaps aren't released except through DeleteDC.
*/
DeleteObject((HBITMAP)hdc->bitmap);
GdItemFree(hdc);
return 1;
}
/* free a dc allocated from CreateCompatibleDC*/
BOOL WINAPI
DeleteDC(HDC hdc)
{
/* don't delete a normal dc, only memory dc's*/
if(!hdc || !(hdc->psd->flags&PSF_MEMORY))
return 0;
/* free allocated memory screen device*/
hdc->psd->FreeMemGC(hdc->psd);
/* make it look like a GetDC dc, and free it*/
hdc->psd = &scrdev;
return ReleaseDC(NULL, hdc);
}
void
MwPaintNCArea(HWND hwnd)
{
SendMessage(hwnd, WM_NCPAINT, 0, 0L);
/* for now, we always paint NC scrollbar areas*/
MwPaintNCScrollbars(hwnd, NULL);
}
HDC WINAPI
BeginPaint(HWND hwnd, LPPAINTSTRUCT lpPaint)
{
HDC hdc;
/* first update non-client area*/
if(mwforceNCpaint || hwnd->paintNC != mwpaintNC) {
MwPaintNCArea(hwnd);
hwnd->paintNC = mwpaintNC;
}
/* If ERASEMOVE:
* Don't allow windows to repaint while user is moving
* a window. Instead, just erase backgrounds
* and indicate delayed painting required, which
* will occur after user completes window move.
*/
if(mwERASEMOVE && dragwp) {
hdc = NULL;
lpPaint->fErase = !DefWindowProc(hwnd, WM_ERASEBKGND, 0, 0L);
hwnd->gotPaintMsg = PAINT_DELAYPAINT;
} else {
HideCaret(hwnd);
/* FIXME: mdemo requires update excluded or draw errors occur*/
hdc = GetDCEx(hwnd, NULL, DCX_DEFAULTCLIP
|DCX_EXCLUDEUPDATE); /* FIXME - bug*/
/* erase client background*/
lpPaint->fErase = !SendMessage(hwnd, WM_ERASEBKGND, (WPARAM)hdc,
0L);
}
lpPaint->hdc = hdc;
GetUpdateRect(hwnd, &lpPaint->rcPaint, FALSE);
return hdc;
}
BOOL WINAPI
EndPaint(HWND hwnd, CONST PAINTSTRUCT *lpPaint)
{
ReleaseDC(hwnd, lpPaint->hdc);
#if UPDATEREGIONS
/* don't clear update region until done dragging*/
if(mwERASEMOVE && !dragwp)
GdSetRectRegion(hwnd->update, 0, 0, 0, 0);
#endif
ShowCaret(hwnd);
return TRUE;
}
COLORREF WINAPI
SetTextColor(HDC hdc, COLORREF crColor)
{
COLORREF oldtextcolor;
if (!hdc)
return CLR_INVALID;
oldtextcolor = hdc->textcolor;
hdc->textcolor = (MWCOLORVAL)crColor;
return oldtextcolor;
}
COLORREF WINAPI
SetBkColor(HDC hdc, COLORREF crColor)
{
COLORREF oldbkcolor;
if (!hdc)
return CLR_INVALID;
oldbkcolor = hdc->bkcolor;
hdc->bkcolor = crColor;
return oldbkcolor;
}
int WINAPI
SetBkMode(HDC hdc, int iBkMode)
{
int oldbkmode;
if(!hdc)
return 0;
oldbkmode = hdc->bkmode;
hdc->bkmode = iBkMode;
return oldbkmode;
}
UINT WINAPI
SetTextAlign(HDC hdc, UINT fMode)
{
UINT oldfMode;
if(!hdc)
return GDI_ERROR;
oldfMode = hdc->textalign;
hdc->textalign = fMode;
return oldfMode;
}
/* FIXME: releasing a DC does NOT change back the drawing mode!*/
int WINAPI
SetROP2(HDC hdc, int fnDrawMode)
{
int newmode, oldmode;
if(!hdc || (fnDrawMode <= 0 || fnDrawMode > R2_LAST))
return 0;
oldmode = hdc->drawmode;
newmode = fnDrawMode - 1; /* map to MWMODE_xxx*/
hdc->drawmode = newmode;
GdSetMode(newmode);
return oldmode;
}
/*
* Setup clip region from device context's associated window or bitmap.
* Memory DC's are always associated with the desktop window, and are
* always visible. Return the DC's hwnd if window is visible.
*/
HWND
MwPrepareDC(HDC hdc)
{
HWND hwnd;
if(!hdc || !hdc->hwnd)
return NULL;
hwnd = hdc->hwnd;
if (hwnd->unmapcount)
return NULL;
/*
* If the window is not the currently clipped one, then
* make it the current one and define its clip rectangles.
*/
if(hdc != cliphdc) {
/* clip memory dc's to the bitmap size*/
if(hdc->psd->flags&PSF_MEMORY) {
#if DYNAMICREGIONS
GdSetClipRegion(hdc->psd,
GdAllocRectRegion(0, 0, hdc->psd->xvirtres,
hdc->psd->yvirtres));
#else
static MWCLIPRECT crc = {0, 0, 0, 0};
crc.width = hdc->psd->xvirtres;
crc.height = hdc->psd->yvirtres;
GdSetClipRects(hdc->psd, 1, &crc);
#endif
} else MwSetClipWindow(hdc);
cliphdc = hdc;
}
return hwnd;
}
/* return RGB value at specified coordinates*/
COLORREF WINAPI
GetPixel(HDC hdc, int x, int y)
{
HWND hwnd;
POINT pt;
MWPIXELVAL pixel;
MWPALENTRY rgb;
hwnd = MwPrepareDC(hdc);
if(!hwnd)
return CLR_INVALID;
pt.x = x;
pt.y = y;
if(MwIsClientDC(hdc))
ClientToScreen(hwnd, &pt);
/* read pixel value*/
GdReadArea(hdc->psd, pt.x, pt.y, 1, 1, &pixel);
switch(hdc->psd->pixtype) {
case MWPF_TRUECOLOR0888:
case MWPF_TRUECOLOR888:
/* create RGB colorval from 8/8/8 pixel*/
return PIXEL888TOCOLORVAL(pixel);
case MWPF_TRUECOLOR565:
/* create RGB colorval from 5/6/5 pixel*/
return PIXEL565TOCOLORVAL(pixel);
case MWPF_TRUECOLOR555:
/* create RGB colorval from 5/5/5 pixel*/
return PIXEL555TOCOLORVAL(pixel);
case MWPF_TRUECOLOR332:
/* create RGB colorval from 3/3/2 pixel*/
return PIXEL332TOCOLORVAL(pixel);
case MWPF_TRUECOLOR233:
/* create RGB colorval from 2/3/3 pixel*/
return PIXEL233TOCOLORVAL(pixel);
case MWPF_PALETTE:
if(GdGetPalette(hdc->psd, pixel, 1, &rgb))
return RGB(rgb.r, rgb.g, rgb.b);
}
return CLR_INVALID;
}
COLORREF WINAPI
SetPixel(HDC hdc, int x, int y, COLORREF crColor)
{
HWND hwnd;
POINT pt;
hwnd = MwPrepareDC(hdc);
if(!hwnd)
return 0; /* doesn't return previous color*/
pt.x = x;
pt.y = y;
if(MwIsClientDC(hdc))
ClientToScreen(hwnd, &pt);
/* draw point in passed color*/
GdSetForeground(GdFindColor(crColor));
GdPoint(hdc->psd, pt.x, pt.y);
return 0; /* doesn't return previous color*/
}
BOOL WINAPI
MoveToEx(HDC hdc, int x, int y, LPPOINT lpPoint)
{
if(!hdc)
return FALSE;
if(lpPoint)
*lpPoint = hdc->pt;
hdc->pt.x = x;
hdc->pt.y = y;
return TRUE;
}
BOOL WINAPI
LineTo(HDC hdc, int x, int y)
{
HWND hwnd;
POINT beg, end;
hwnd = MwPrepareDC(hdc);
if(!hwnd)
return FALSE;
beg.x = hdc->pt.x;
beg.y = hdc->pt.y;
end.x = x;
end.y = y;
if(MwIsClientDC(hdc)) {
ClientToScreen(hwnd, &beg);
ClientToScreen(hwnd, &end);
}
/* draw line in current pen color*/
if(hdc->pen->style != PS_NULL) {
GdSetForeground(GdFindColor(hdc->pen->color));
/* don't draw last point*/
GdLine(hdc->psd, beg.x, beg.y, end.x, end.y, FALSE);
}
hdc->pt.x = x;
hdc->pt.y = y;
return TRUE;
}
/* draw line segments by connecting passed points*/
BOOL WINAPI
Polyline(HDC hdc, CONST POINT *lppt, int cPoints)
{
HWND hwnd;
POINT beg, end;
if(cPoints <= 1)
return FALSE;
hwnd = MwPrepareDC(hdc);
if(!hwnd)
return FALSE;
if(hdc->pen->style == PS_NULL)
return TRUE;
/* draw line in current pen color*/
GdSetForeground(GdFindColor(hdc->pen->color));
beg = *lppt++;
if(MwIsClientDC(hdc))
ClientToScreen(hwnd, &beg);
while(--cPoints > 0) {
end = *lppt++;
if(MwIsClientDC(hdc))
ClientToScreen(hwnd, &end);
/* don't draw last point*/
GdLine(hdc->psd, beg.x, beg.y, end.x, end.y, FALSE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -