/*-----------------------------------------
HELLOBIT.C – 在内存设备内容中的位图上输出
文字
-----------------------------------------*/
#include <windows.h>
#include "resource.h"
LRESULT
CALLBACK
WndProc (
HWND
,
UINT
,
WPARAM
,
LPARAM) ;
int
WINAPI
WinMain (
HINSTANCE
hInstance
,
HINSTANCE
hPrevInstance
,
PSTR
szCmdLine
,
int
iCmdShow)
{
static
TCHAR
szAppName
[]
=
TEXT (
"HelloBit") ;
HWND
hwnd ;
MSG
msg ;
WNDCLASS
wndclass ;
wndclass
.
style
=
CS_HREDRAW |
CS_VREDRAW ;
wndclass
.
lpfnWndProc
=
WndProc ;
wndclass
.
cbClsExtra
=
0 ;
wndclass
.
cbWndExtra
=
0 ;
wndclass
.
hInstance
=
hInstance ;
wndclass
.
hIcon
=
LoadIcon (
NULL
,
IDI_APPLICATION) ;
wndclass
.
hCursor
=
LoadCursor (
NULL
,
IDC_ARROW) ;
wndclass
.
hbrBackground
= (
HBRUSH)
GetStockObject (
WHITE_BRUSH) ;
wndclass
.
lpszMenuName
=
szAppName ;
wndclass
.
lpszClassName
=
szAppName ;
if (
!
RegisterClass (
&
wndclass))
{
MessageBox (
NULL
,
TEXT (
"This program requires Windows NT!"
),
szAppName
,
MB_ICONERROR) ;
return
0 ;
}
hwnd
=
CreateWindow (
szAppName
,
TEXT (
"HelloBit"
),
WS_OVERLAPPEDWINDOW
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
NULL
,
NULL
,
hInstance
,
NULL) ;
ShowWindow (
hwnd
,
iCmdShow) ;
UpdateWindow (
hwnd) ;
while (
GetMessage (
&
msg
,
NULL
,
0
,
0))
{
TranslateMessage (
&
msg) ;
DispatchMessage (
&
msg) ;
}
return
msg
.
wParam ;
}
LRESULT
CALLBACK
WndProc (
HWND
hwnd
,
UINT
message
,
WPARAM
wParam
,
LPARAM
lParam)
{
static
HBITMAP
hBitmap ;
static
HDC
hdcMem ;
static
int
cxBitmap
,
cyBitmap
,
cxClient
,
cyClient
,
iSize
=
IDM_BIG ;
static
TCHAR
*
szText
=
TEXT (
" Hello, world! ") ;
HDC
hdc ;
HMENU
hMenu ;
int
x
,
y ;
PAINTSTRUCT ps ;
SIZE
size ;
switch (
message)
{
case
WM_CREATE:
hdc
=
GetDC (
hwnd) ;
//取整个窗体的设备内容句柄
hdcMem
=
CreateCompatibleDC (
hdc) ;
//建立与视讯显示器兼容的内存设备内容
//计算字符串的高度和宽度的图素尺寸
//lstrlen (szText) 计算字符串的字符数
GetTextExtentPoint32 (
hdc
,
szText
,
lstrlen (
szText
),
&
size) ;
cxBitmap
=
size
.
cx ;
cyBitmap
=
size
.
cy ;
//以字符串的宽度和高度来设定位图大小
//建立与设备内容兼容的位图,大小为上面计算的字符串宽高
hBitmap
=
CreateCompatibleBitmap (
hdc
,
cxBitmap
,
cyBitmap) ;
ReleaseDC (
hwnd
,
hdc) ;
//释放设备内容句柄
SelectObject (
hdcMem
,
hBitmap) ;
//将建立的位图选进内存设备内容
//在内存设备内容上输出字符串
TextOut (
hdcMem
,
0
,
0
,
szText
,
lstrlen (
szText)) ;
return
0 ;
case
WM_SIZE:
cxClient
=
LOWORD (
lParam) ;
cyClient
=
HIWORD (
lParam) ;
return
0 ;
case
WM_COMMAND:
hMenu
=
GetMenu (
hwnd) ;
//取得窗体的菜单句柄
switch (
LOWORD (
wParam))
{
case
IDM_BIG:
case
IDM_SMALL:
//删除iSize所对应的菜单的选取标记
CheckMenuItem (
hMenu
,
iSize
,
MF_UNCHECKED) ;
iSize
=
LOWORD (
wParam) ;
//读取当前选择的菜单项
CheckMenuItem (
hMenu
,
iSize
,
MF_CHECKED) ;
//标记当前选择的菜单项
InvalidateRect (
hwnd
,
NULL
,
TRUE) ;
//要求系统重绘整个窗体
break ;
}
return
0 ;
case
WM_PAINT:
hdc
=
BeginPaint (
hwnd
,
&ps) ;
switch (
iSize)
{
case
IDM_BIG:
//拉伸位图到整个窗体
StretchBlt (
hdc
,
0
,
0
,
cxClient
,
cyClient
,
hdcMem
,
0
,
0
,
cxBitmap
,
cyBitmap
,
SRCCOPY) ;
break ;
case
IDM_SMALL:
//平铺位图到窗体
for (
y
=
0 ;
y
<
cyClient ;
y
+=
cyBitmap)
for (
x
=
0 ;
x
<
cxClient ;
x
+=
cxBitmap)
{
BitBlt (
hdc
,
x
,
y
,
cxBitmap
,
cyBitmap
,
hdcMem
,
0
,
0
,
SRCCOPY) ;
}
break ;
}
EndPaint (
hwnd
,
&ps) ;
return
0 ;
case
WM_DESTROY:
DeleteDC (
hdcMem) ;
//删除内存设备内容
DeleteObject (
hBitmap) ;
//删除建立的位图
PostQuitMessage (
0) ;
return
0 ;
}
return
DefWindowProc (
hwnd
,
message
,
wParam
,
lParam) ;
}
/*-----------------------------------------
HelloBit.rc – HELLOBIT.C资源文件
-----------------------------------------*/
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE
LANG_ENGLISH
,
SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif
//_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1
TEXTINCLUDE
DISCARDABLE
BEGIN
"resource.h
/0
"
END
2
TEXTINCLUDE
DISCARDABLE
BEGIN
"#include ""afxres.h""
/r/n
"
"
/0
"
END
3
TEXTINCLUDE
DISCARDABLE
BEGIN
"
/r/n
"
"
/0
"
END
#endif
// APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
HELLOBIT
MENU
DISCARDABLE
BEGIN
POPUP
"&Size"
BEGIN
MENUITEM
"&Big"
,
IDM_BIG
,
CHECKED
MENUITEM
"&Small"
,
IDM_SMALL
END
END
#endif
// English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif
// not APSTUDIO_INVOKED
/*-----------------------------------------
RESOURCE.H – HELLOBIT.C资源头文件
-----------------------------------------*/
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by HelloBit.rc
//
#define IDM_BIG 40001
#define IDM_SMALL 40002
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40003
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
/*-----------------------------------------
SKETCH.C – 在显示设备内容和内存设备内容
上绘画
-----------------------------------------*/
#include <windows.h>
LRESULT
CALLBACK
WndProc (
HWND
,
UINT
,
WPARAM
,
LPARAM) ;
int
WINAPI
WinMain (
HINSTANCE
hInstance
,
HINSTANCE
hPrevInstance
,
PSTR
szCmdLine
,
int
iCmdShow)
{
static
TCHAR
szAppName
[]
=
TEXT (
"Sketch") ;
HWND
hwnd ;
MSG
msg ;
WNDCLASS
wndclass ;
wndclass
.
style
=
CS_HREDRAW |
CS_VREDRAW ;
wndclass
.
lpfnWndProc
=
WndProc ;
wndclass
.
cbClsExtra
=
0 ;
wndclass
.
cbWndExtra
=
0 ;
wndclass
.
hInstance
=
hInstance ;
wndclass
.
hIcon
=
LoadIcon (
NULL
,
IDI_APPLICATION) ;
wndclass
.
hCursor
=
LoadCursor (
NULL
,
IDC_ARROW) ;
wndclass
.
hbrBackground
= (
HBRUSH)
GetStockObject (
WHITE_BRUSH) ;
wndclass
.
lpszMenuName
=
NULL ;
wndclass
.
lpszClassName
=
szAppName ;
if (
!
RegisterClass (
&
wndclass))
{
MessageBox (
NULL
,
TEXT (
"This program requires Windows NT!"
),
szAppName
,
MB_ICONERROR) ;
return
0 ;
}
hwnd
=
CreateWindow (
szAppName
,
TEXT (
"Sketch"
),
WS_OVERLAPPEDWINDOW
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
NULL
,
NULL
,
hInstance
,
NULL) ;
if (
hwnd
==
NULL)
{
MessageBox (
NULL
,
TEXT (
"Not enough memory to create bitmap!"
),
szAppName
,
MB_ICONERROR) ;
return
0 ;
}
ShowWindow (
hwnd
,
iCmdShow) ;
UpdateWindow (
hwnd) ;
while (
GetMessage (
&
msg
,
NULL
,
0
,
0))
{
TranslateMessage (
&
msg) ;
DispatchMessage (
&
msg) ;
}
return
msg
.
wParam ;
}
void
GetLargestDisplayMode (
int
*
pcxBitmap
,
int
*
pcyBitmap)
{
DEVMODE
devmode ;
int
iModeNum
=
0 ;
*
pcxBitmap
=
*
pcyBitmap
=
0 ;
//用0来填充devmode内存区域
ZeroMemory (
&
devmode
,
sizeof (
DEVMODE)) ;
devmode
.
dmSize
=
sizeof (
DEVMODE) ;
//获取调用线程正运行在计算机的当前显示设备所有的图形模式信息,记录在devmode结构中
//枚举调用,使其能获得当前显示设备的最大显示尺寸
while (
EnumDisplaySettings (
NULL
,
iModeNum
++
,
&
devmode))
{
//取当前显示设备宽和高来设置位图尺寸,以像素为单位。MAX宏限制了该数不可为负数
*
pcxBitmap
=
max (
*
pcxBitmap
, (
int)
devmode
.
dmPelsWidth) ;
*
pcyBitmap
=
max (
*
pcyBitmap
, (
int)
devmode
.
dmPelsHeight) ;
}
}
LRESULT
CALLBACK
WndProc (
HWND
hwnd
,
UINT
message
,
WPARAM
wParam
,
LPARAM
lParam)
{
static
BOOL
fLeftButtonDown
,
fRightButtonDown ;
static
HBITMAP
hBitmap ;
static
HDC
hdcMem ;
static
int
cxBitmap
,
cyBitmap
,
cxClient
,
cyClient
,
xMouse
,
yMouse ;
HDC
hdc ;
PAINTSTRUCT ps ;
switch (
message)
{
case
WM_CREATE:
//调用自定义函数,取当前显示设备的最大尺寸来设定位图尺寸
GetLargestDisplayMode (
&
cxBitmap
,
&
cyBitmap) ;
hdc
=
GetDC (
hwnd) ;
//取整个程序窗体的句柄
//建立与显示设备兼容的位图
hBitmap
=
CreateCompatibleBitmap (
hdc
,
cxBitmap
,
cyBitmap) ;
//建立与显示设备兼容的内存设备内容
hdcMem
=
CreateCompatibleDC (
hdc) ;
ReleaseDC (
hwnd
,
hdc) ;
//删除窗体句柄
//判断位图是否成功建立,如果CreateCompatibleBitmap调用失败,hBitmap值为NULL
if (
!
hBitmap)
{
//删除内存设备内容,并返回-1的错误消息
DeleteDC (
hdcMem) ;
return
-
1 ;
}
//将建立的位图选进内存设备内容,等于是扩充内存设备内容
SelectObject (
hdcMem
,
hBitmap) ;
//将内存设备内容中的位图刷成白色
PatBlt (
hdcMem
,
0
,
0
,
cxBitmap
,
cyBitmap
,
WHITENESS) ;
return
0 ;
case
WM_SIZE:
cxClient
=
LOWORD (
lParam) ;
cyClient
=
HIWORD (
lParam) ;
return
0 ;
case
WM_LBUTTONDOWN:
//鼠标左键按下
//如果鼠标右键已经释放,则为当前窗口捕获鼠标
if (
!
fRightButtonDown)
SetCapture (
hwnd) ;
//获取鼠标光标相对于客户区域左上角的坐标
xMouse
=
LOWORD (
lParam) ;
yMouse
=
HIWORD (
lParam) ;
//设置鼠标左键按下标记
fLeftButtonDown
=
TRUE ;
return
0 ;
case
WM_LBUTTONUP:
//鼠标左键释放
//如果鼠标左键按下标记被设置,则释放先前的鼠标捕获
if (
fLeftButtonDown)
SetCapture (
NULL) ;
//设置鼠标左键释放标记
fLeftButtonDown
=
FALSE ;
return
0 ;
case
WM_RBUTTONDOWN:
//鼠标右键按下
//如果鼠标左键已经释放,则为当前窗口捕获鼠标
if (
!
fLeftButtonDown)
SetCapture (
hwnd) ;
//获取鼠标光标相对于客户区域左上角的坐标
xMouse
=
LOWORD (
lParam) ;
yMouse
=
HIWORD (
lParam) ;
//设置鼠标右键按下标记
fRightButtonDown
=
TRUE ;
return
0 ;
case
WM_RBUTTONUP:
//鼠标右键释放
//如果鼠标右键按下标记被设置,则释放先前的鼠标捕获
if (
fRightButtonDown)
SetCapture (
NULL) ;
//设置鼠标右键释放标记
fRightButtonDown
=
FALSE ;
return
0 ;
case
WM_MOUSEMOVE:
//如果鼠标左右键均已释放,则直接返回
if (
!
fLeftButtonDown
&&
!
fRightButtonDown)
return
0 ;
hdc
=
GetDC (
hwnd) ;
//取得程序的整个窗体句柄
//将相应的钢笔句柄选进设备内容中
SelectObject (
hdc
,
//鼠标左键按下则获取黑色钢笔句柄,否则取白色钢笔句柄
GetStockObject (
fLeftButtonDown
?
BLACK_PEN
:
WHITE_PEN)) ;
//在内存设备内容中做相同操作
SelectObject (
hdcMem
,
GetStockObject (
fLeftButtonDown
?
BLACK_PEN
:
WHITE_PEN)) ;
//移动画线起始点到鼠标按下时所保存的位置
MoveToEx (
hdc
,
xMouse
,
yMouse
,
NULL) ;
MoveToEx (
hdcMem
,
xMouse
,
yMouse
,
NULL) ;
//获取当前鼠标移动到的位置
xMouse
= (
short)
LOWORD (
lParam) ;
yMouse
= (
short)
HIWORD (
lParam) ;
//在窗口和内存设备内容中的位图上划线
LineTo (
hdc
,
xMouse
,
yMouse) ;
LineTo (
hdcMem
,
xMouse
,
yMouse) ;
ReleaseDC (
hwnd
,
hdc) ;
//删除窗体设备内容句柄
return
0 ;
case
WM_PAINT:
hdc
=
BeginPaint (
hwnd
,
&ps) ;
//当显示区域重绘时,用内存设备内容中的位图来更新
//这一设置与鼠标捕获结合时,可以在窗口以外屏幕之内作画,通过拉伸窗口来显示隐藏的数据
BitBlt (
hdc
,
0
,
0
,
cxClient
,
cyClient
,
hdcMem
,
0
,
0
,
SRCCOPY) ;
EndPaint (
hwnd
,
&ps) ;
return
0 ;
case
WM_DESTROY:
//释放内存设备内容和建立的位图
DeleteDC (
hdcMem) ;
DeleteObject (
hBitmap) ;
PostQuitMessage (
0) ;
return
0 ;
}
return
DefWindowProc (
hwnd
,
message
,
wParam
,
lParam) ;
}