No.007 - 07 直線描画 |
| Bresenham(ブレゼンハム)の直線描画を行います。 Jack Bresenham さんはアメリカのWinthrop(ウィンスロップ)大学のコンピュータ科学の教授だそうです。 (ちなみにBresenhamアルゴリズムをgoogleで検索するとかなりコード間違えてるサイトが上位にくるので注意してね。 2005.5) |
・直線描画 |
|||||||||||||||||||||||||||||||||||||
| 直線描画において、一般的な数学の公式を使うと、傾きなどを求めるときにどうしても誤差がでてしまいます。 また誤差がでないように全長からの比率で位置計算を行うと、割り算を使う都合上、非常に遅いルーチンになります。 なのでブレゼンハム方式で直線描画を行います。 ブレゼンハム方式は全てが整数演算で、割り算もないので非常に正確高速です。 |
|||||||||||||||||||||||||||||||||||||
・Bresenham(ブレゼンハム)の考え方 |
|||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||
…要は0.1 ずつ足して1になったかどうか調べるんじゃなくて、1ずつ足していって10になったかどうか調べるやりかたと同じ。 |
|||||||||||||||||||||||||||||||||||||
・四捨五入 |
|||||||||||||||||||||||||||||||||||||
| 上記の草案2は四捨五入を考えてません。 単純に0.4999…まで切り捨て、0.5で切り上げればいいだけなので、 草案2の e の初期値を 0.5 (=ww/2) にしてやればいいだけです。e=0 → e=ww/2; です。 でも ww/2 は端数があるとき誤差がでます(でても1ですが)。 なので上例のように割り算なくします。
|
|||||||||||||||||||||||||||||||||||||
・直線描画の範囲補正 |
|||||||||||||||||||||||||||||||||||||
| なぜかどこのサイトもやってない範囲補正やります。 通常描画のx, y の初期値はx1, y1です。 x = x1; y = y1; ですが x1, y1がマイナス値だったり画像幅以上の値だったりすることもあるはずなのでその初期値を補正してやります。 当然数学の公式なんぞで補正すれば誤差がでます。端っこ1ピクセル分オーバーしたり届かなかったり。(余算が必要なのです)
|
|||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||
| 下記サンプルソースは6つのファイルから成っています ピクセル反復子や、パレット(色テーブル)クラスを定義するヘッダの gt_img_parts.h と、 定数を定義している resource_07.h 、 画像クラスを定義している gt_img_07.h、 リソーススクリプトの gt_img_07.rc、 BMPファイルを読み書きするgt_img_bmp_io.cpp 、 メインファイルの gt_img_07.cpp です。
|
|||||||||||||||||||||||||||||||||||||
![]() |
||
| ドラッグで線を引くことができます。 |
||
![]() |
→ | ![]() |
| このように画像の範囲外を引いても… |
きちんと描画前に範囲補正して 描画します |
|
![]() |
||
| 色々な直線が引けます | ||
| resource_07.h |
// 直線描画
#include "resource_07.h"
//リソーススクリプト
GT_DIB_MENU MENU {
POPUP "ファイル" {
POPUP "作成" {
MENUITEM "1 bit" , IDM_MAKE_DIB_1
MENUITEM "4 bit" , IDM_MAKE_DIB_4
MENUITEM "8 bit" , IDM_MAKE_DIB_8
MENUITEM "16 bit", IDM_MAKE_DIB_16
MENUITEM "24 bit", IDM_MAKE_DIB_24
MENUITEM "32 bit", IDM_MAKE_DIB_32
}
MENUITEM "ひらく", IDM_OPEN
MENUITEM "保存", IDM_SAVE_DIB
}
MENUITEM "色", IDM_COL
}
|
| gt_img_07.rc |
// 直線描画
#include "resource_07.h"
//リソーススクリプト
GT_DIB_MENU MENU {
POPUP "ファイル" {
POPUP "作成" {
MENUITEM "1 bit" , IDM_MAKE_DIB_1
MENUITEM "4 bit" , IDM_MAKE_DIB_4
MENUITEM "8 bit" , IDM_MAKE_DIB_8
MENUITEM "16 bit", IDM_MAKE_DIB_16
MENUITEM "24 bit", IDM_MAKE_DIB_24
MENUITEM "32 bit", IDM_MAKE_DIB_32
}
MENUITEM "ひらく", IDM_OPEN
MENUITEM "保存", IDM_SAVE_DIB
}
MENUITEM "色", IDM_COL
}
|
| gt_img_07.h |
// 直線描画
#include <stdio.h>
#include <windows.h>
#include "resource_07.h"
#include "gt_img_parts.h"
// ======== GT_IMG ==================================
class GT_IMG {
public :
GT_COL_TABLE m_col_table;
unsigned long *m_col_mask;
char *m_alpha;
int m_width, m_height, m_byte_width, m_bit_count;
BYTE *m_pbits;
GT_IMG();
virtual ~GT_IMG();
// 作成と破棄
virtual destroy();
virtual create(int cx, int cy, int a_bit_count, int a_color_size=0);
// ピクセル描画
set_pixel(int x, int y, DWORD col);
DWORD get_pixel(int x, int y);
// 直線描画
draw_line(int sx, int sy, int ex, int ey, BYTE r, BYTE g, BYTE b, int rate);
template <int d_bit> void draw_line_pixput(int sx, int sy, int ex, int ey, BYTE r, BYTE g, BYTE b, int rate);
adjust_lining_limit(int *p_start, int *p_end, int sx, int sy, int ex, int ey, int *p_cx, int *p_cy);
// アルファ値
is_alpha(){ return (m_alpha!=NULL); }
// カラー
set_col_mask(UINT r, UINT g, UINT b);
set_pal_col(BYTE index, BYTE r, BYTE g, BYTE b);
// 読込
load_dib(char *filename);
load_dib_rle4(HANDLE hfile); // 4bit ランレングス圧縮
load_dib_rle8(HANDLE hfile); // 8bit ランレングス圧縮
// 書込み
save_dib(char *filename, int rle_compress_flag=0);
save_dib_rle4(HANDLE hfile); // 4bit ランレングス圧縮
save_dib_rle8(HANDLE hfile); // 8bit ランレングス圧縮
};
// 直線描画
GT_IMG::draw_line(int sx, int sy, int ex, int ey, BYTE r, BYTE g, BYTE b, int rate){
if (!m_pbits) return -1;
if (sx==ex && sy==ey) return -1;
// 描画
switch(m_bit_count){
case 1 : draw_line_pixput<1> (sx, sy, ex, ey, r, g, b, rate); break;
case 4 : draw_line_pixput<4> (sx, sy, ex, ey, r, g, b, rate); break;
case 8 : draw_line_pixput<8> (sx, sy, ex, ey, r, g, b, rate); break;
case 16: draw_line_pixput<16>(sx, sy, ex, ey, r, g, b, rate); break;
case 24: draw_line_pixput<24>(sx, sy, ex, ey, r, g, b, rate); break;
case 32: draw_line_pixput<32>(sx, sy, ex, ey, r, g, b, rate); break;
}
return 0;
}
// 直線描画のインライン・テンプレート(RGB版)
template <int d_bit> void
GT_IMG::draw_line_pixput(int sx, int sy, int ex, int ey, BYTE r, BYTE g, BYTE b, int rate){
int cx, cy, pos_x, pos_y, i, lim, start, end;
PIXEL_ITR<d_bit,0> d_pix;
if (rate<0) rate=0;
if (rate>=255) rate=255;
d_pix.init(m_pbits, m_alpha, m_byte_width, m_width, m_height, &m_col_table);
int col_index;
double e;
int *p_co1, *p_co2, ddis1, ddis2, dn1, dn2;
if (adjust_lining_limit(&start, &end, sx, sy, ex, ey, &cx, &cy)<0) return;
int base_axis = (abs(cx)>abs(cy))? 'x' : 'y';
p_co1 = (base_axis=='x')? &pos_x : &pos_y;
p_co2 = (base_axis=='x')? &pos_y : &pos_x;
ddis1 = (base_axis=='x')? 2*cx : 2*cy;
ddis2 = (base_axis=='x')? 2*cy : 2*cx;
dn1 = dn2 = 1;
if (ddis1<0) { dn1=-1; ddis1 = -ddis1; }
if (ddis2<0) { dn2=-1; ddis2 = -ddis2; }
pos_x = sx;
pos_y = sy;
*p_co1 += dn1* start;
*p_co2 += dn2* (start*ddis2+ddis1/2) /ddis1;
e = (ddis1/2 + start*ddis2)%ddis1;
if (d_bit<8){ // (パレット版)
col_index = m_col_table.get_col_index<d_bit>(r*rate/255, g*rate/255, b*rate/255);
for(i=start;i<=end;i++){
d_pix.set_pos(pos_x, pos_y);
d_pix.set_col(col_index);
(*p_co1)+=dn1;
e += ddis2;
if (e>=ddis1){
e -= ddis1;
(*p_co2)+=dn2;
}
}
}
else { // (RGB版)
for(i=start;i<=end;i++){
d_pix.set_pos(pos_x, pos_y);
d_pix.set_col(r, g, b, rate);
(*p_co1)+=dn1;
e += ddis2;
if (e>=ddis1){
e -= ddis1;
(*p_co2)+=dn2;
}
}
}
return ;
};
// 直線描画 補正
GT_IMG::adjust_lining_limit(int *p_start, int *p_end, int sx, int sy, int ex, int ey, int *p_cx, int *p_cy){
int img_lim, img_lim_other, base_lim, other_lim;
int *p_res, base_co, other_co, tmp, cx, cy;
cx=*p_cx=ex-sx;
cy=*p_cy=ey-sy;
int base_axis = (abs(cx)>abs(cy))? 'x' : 'y';
*p_start = *p_end = 0;
if (!cx && !cy) return -1;
// x,yの長いほうの座標軸をベースにする
if (base_axis=='x'){ // x 座標ベース
img_lim = m_width;
img_lim_other = m_height;
base_lim = cx;
other_lim = cy;
}
else{ // y 座標ベース
img_lim = m_height;
img_lim_other = m_width;
base_lim = cy;
other_lim = cx;
}
for(int i=0;i<2;i++){
if (i==0) {
p_res = p_start;
base_co = (base_axis=='x')? sx : sy;
other_co = (base_axis=='x')? sy : sx;
}
else if (i==1) {
p_res = p_end;
base_co = (base_axis=='x')? ex : ey;
other_co = (base_axis=='x')? ey : ex;
other_lim = -other_lim;
}
// x,yの長いほうの座標軸で判定
if (base_co<0) *p_res=-base_co;
if (base_co>=img_lim) *p_res= base_co-img_lim+1;
// x,yの短いほうの座標軸で判定
if (!other_lim) continue;
tmp = other_co + ((*p_res) * (2*other_lim) + abs(base_lim))/(2*base_lim);
int aim_co;
if (tmp<0) { aim_co = -other_co; }
else if (tmp>=img_lim_other) { aim_co = other_co-img_lim_other+1; }
else continue; // 範囲内
tmp = aim_co*2*abs(base_lim)-abs(base_lim);
*p_res = tmp/abs(2*other_lim);
if (i==0 && tmp%abs(2*other_lim)) (*p_res)++;
if (i==1) (*p_res)++;
}
*p_end = abs(base_lim) - *p_end;
return 0;
}
// コンストラクタ
GT_IMG::GT_IMG(){
m_col_mask =NULL;
m_alpha =NULL;
m_width = m_height = m_byte_width = m_bit_count =0;
m_pbits =NULL;
}
// デストラクタ
GT_IMG::~GT_IMG(){
destroy();
}
// GIMG 破棄
GT_IMG::destroy(){
m_width=0;
m_height=0;
m_byte_width=0;
m_bit_count=0;
if (m_pbits) delete[] m_pbits;
m_pbits = NULL;
if (m_col_mask) delete[] m_col_mask;
m_col_mask = NULL;
m_col_table.destroy();
return 0;
};
// GIMG 作成
GT_IMG::create(int cx, int cy, int a_bit_count, int a_color_size){
int i, palette_len, info_size;
destroy(); // ファイルが開けたら既存データ破棄
if (cx<=0 || cy<=0) return -1;
if (a_bit_count!=1 && a_bit_count!=4 && a_bit_count!=8
&& a_bit_count!=16 && a_bit_count!=24 && a_bit_count!=32) return -1;
if (a_bit_count<=8 && a_color_size==0) palette_len=1<<a_bit_count; // 8bit以下でパレット色数指定無しなら
else palette_len=a_color_size;
// パレット・メモリ確保
m_col_table.make(palette_len);
/* バッファの1ラインの長さを計算 */
m_byte_width=4*((cx*a_bit_count+31)/32);
m_pbits = new BYTE[m_byte_width*cy];
ZeroMemory(m_pbits, m_byte_width*cy);
if (!m_pbits) return -1;
m_width= cx;
m_height=cy;
m_bit_count=a_bit_count;
// パレット自動配色
// 適当な基本色
RGBTRIPLE rgb[8]={
{0,0,0},{255, 255, 255}, {0,0,255}, {255,0,0}, {0,255,0}, {255, 255,0}, {255,0,255},{0,255,255}
};
for(i=0;i<min(palette_len, 8);i++){
m_col_table.add_col(rgb[i].rgbtRed, rgb[i].rgbtGreen, rgb[i].rgbtBlue);
}
return 0;
}
// パレットに色設定
inline GT_IMG::set_pal_col(BYTE index, BYTE r, BYTE g, BYTE b){
if (m_col_table.m_cols_len<=index) return 0;
m_col_table.set_col(index, r, g, b);
return 0;
}
// カラーマスク設定
GT_IMG::set_col_mask(UINT r, UINT g, UINT b){
if (!m_col_mask) m_col_mask = new unsigned long[3];
m_col_mask[0] = r;
m_col_mask[1] = g;
m_col_mask[2] = b;
}
// 1点ピクセル取得
DWORD GT_IMG::get_pixel(int x, int y){
if (!m_pbits) return 0;
if (x<0 || x>=m_width || y<0 || y>=m_height) return 0;
BYTE *ppix;
ppix=m_pbits+(m_height-y-1)*m_byte_width + (x*m_bit_count>>3);
switch(m_bit_count){
case 1: return 0x01 & (*ppix >> (7-(x&7)));
case 4: return 0x0f & (*ppix >> ((x&1)?0:4));
case 8: return *ppix ;
case 16: return *(WORD*)ppix;
case 24: return 0x00FFffFF & *(DWORD*)ppix;
case 32: return *(DWORD*)ppix ;
}
return 0;
}
// 1点ピクセル書きこみ
GT_IMG::set_pixel(int x, int y, DWORD col){
if (!m_pbits) return 0;
if (x<0 || x>=m_width || y<0 || y>=m_height) return 0;
BYTE *ppix;
ppix=m_pbits+(m_height-y-1)*m_byte_width + (x*m_bit_count>>3);
switch(m_bit_count){
case 1: *ppix &= ~(1 <<(7-(x&7)));
*ppix |= ((bool)col) <<(7-(x&7));
break;
case 4: *ppix &= 0x0f << ((x&1)?4:0);
*ppix |= (0x0f & col) << ((x&1)?0:4);
break;
case 8: *ppix = (BYTE)col; break;
case 16: *(WORD*)ppix = (WORD)col; break;
case 24: *(RGBTRIPLE*)ppix = *(RGBTRIPLE*)&col; break;
case 32: *(DWORD*)ppix = *(DWORD*)&col; break;
}
return 0;
}
// ======== GT_DIB ==================================
class GT_DIB : public GT_IMG{
public :
HDC m_hdc;
HBITMAP m_hbmp;
GT_DIB();
~GT_DIB();
// DC 適用
apply_dc(HDC hdc);
apply_dc(HWND hwnd);
// 作成と破棄
create(int cx, int cy, int a_bit_count, int a_color_size=0);
virtual destroy();
// カラー
apply_palette_all();
set_pal_col(BYTE index, BYTE r, BYTE g, BYTE b);
};
// コンストラクタ
GT_DIB::GT_DIB(){
m_hdc = NULL;
m_hbmp = NULL;
}
// デストラクタ
GT_DIB::~GT_DIB(){
destroy();
}
// HDCパレット設定(全て)
GT_DIB::apply_palette_all(){
return m_col_table.apply_palette_all(m_hdc);
}
// パレットに色設定
inline GT_DIB::set_pal_col(BYTE index, BYTE r, BYTE g, BYTE b){
return m_col_table.set_pal_col(m_hdc, index, r, g, b);
}
// DC有効化
GT_DIB::apply_dc(HDC hdc){
if (m_hdc) { DeleteDC(m_hdc); m_hdc=NULL; }
m_hdc = CreateCompatibleDC(hdc);
SelectObject(m_hdc, m_hbmp);
return 0;
}
// DC有効化(HWND hwnd)
GT_DIB::apply_dc(HWND hwnd){
if (m_hdc) { DeleteDC(m_hdc); m_hdc=NULL; }
HDC hwnd_hdc = GetDC(hwnd);
m_hdc = CreateCompatibleDC(hwnd_hdc);
SelectObject(m_hdc, m_hbmp);
ReleaseDC(hwnd, hwnd_hdc);
return 0;
}
// 破棄
GT_DIB::destroy(){
if (m_hdc) { DeleteDC(m_hdc); m_hdc=NULL; }
if (m_hbmp) { DeleteObject(m_hbmp); m_hbmp=NULL; }
// if (m_pbits) delete[] m_pbits;
m_pbits = NULL;
m_width=0;
m_height=0;
m_byte_width=0;
m_bit_count=0;
if (m_col_mask) delete[] m_col_mask;
m_col_mask = NULL;
m_col_table.destroy();
return 0;
}
// 作成
GT_DIB::create(int cx, int cy, int a_bit_count, int a_color_size){
BITMAPINFO *bmp_info;
int i, palette_entry, info_size;
destroy(); // 作成済みメモリを破棄する
if (cx<=0 || cy<=0) return -1;
if (a_bit_count!=1 && a_bit_count!=4 && a_bit_count!=8
&& a_bit_count!=16 && a_bit_count!=24 && a_bit_count!=32) return -1;
palette_entry=1;
if (a_color_size!=0) palette_entry=a_color_size;
else if (a_bit_count<=8) palette_entry=1<<a_bit_count; // 8bit以下でパレット色数指定無しなら
info_size=sizeof(BITMAPINFOHEADER) + (palette_entry-1)*sizeof(RGBQUAD)+1;
bmp_info = (BITMAPINFO*)malloc(info_size);
if (!bmp_info) return -1;
ZeroMemory(bmp_info, info_size);
// 適当な基本色
RGBTRIPLE rgb[8]={
{0,0,0},{255, 255, 255}, {0,0,255}, {255,0,0}, {0,255,0}, {255, 255,0}, {255,0,255},{0,255,255}
};
m_col_table.make(palette_entry);
for(i=0;i<min(palette_entry, 8);i++){
bmp_info->bmiColors[i].rgbBlue = rgb[i].rgbtBlue;
bmp_info->bmiColors[i].rgbGreen = rgb[i].rgbtGreen;
bmp_info->bmiColors[i].rgbRed = rgb[i].rgbtRed;
bmp_info->bmiColors[i].rgbReserved = 0;
m_col_table.add_col(rgb[i].rgbtRed, rgb[i].rgbtGreen, rgb[i].rgbtBlue);
}
/* BITMAPINFO構造体設定 */
bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
bmp_info->bmiHeader.biWidth=cx;
bmp_info->bmiHeader.biHeight=cy;
bmp_info->bmiHeader.biPlanes=1;
bmp_info->bmiHeader.biBitCount=a_bit_count;
bmp_info->bmiHeader.biCompression=BI_RGB;
bmp_info->bmiHeader.biSizeImage=0;
bmp_info->bmiHeader.biXPelsPerMeter=0;
bmp_info->bmiHeader.biYPelsPerMeter=0;
bmp_info->bmiHeader.biClrUsed=palette_entry;
bmp_info->bmiHeader.biClrImportant=0;
m_hbmp = CreateDIBSection(NULL, bmp_info, DIB_RGB_COLORS, (VOID**)&m_pbits, NULL, 0);
if (!m_hbmp) {
free(bmp_info);
return -1;
}
m_width= cx;
m_height=cy;
m_bit_count=a_bit_count;
/* バッファの1ラインの長さを計算 */
m_byte_width=4*((m_width*m_bit_count+31)/32);
ZeroMemory(m_pbits, m_byte_width*m_height);
free(bmp_info);
return 0;
}
|
| gt_img_07.cpp |
// 直線描画
#include "gt_img_07.h"
GT_DIB gt_dib_1;
DWORD col=0xffffff;
static OPENFILENAME ofn = {0};
static char filename[MAX_PATH];
POINT start_po, end_po;
CHOOSECOLOR cc = {0};
DWORD col_costom[8] = {0};
BYTE r=255, g=255, b=255;
COLORREF color=0xffffff;
int col_index=0;
// メニュー
on_command(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp){
switch(LOWORD(wp)) {
case IDM_MAKE_DIB_0:
case IDM_MAKE_DIB_1:
case IDM_MAKE_DIB_4:
case IDM_MAKE_DIB_8:
case IDM_MAKE_DIB_16:
case IDM_MAKE_DIB_24:
case IDM_MAKE_DIB_32:
gt_dib_1.create(201, 151, LOWORD(wp)-IDM_MAKE_DIB_0, 0);
gt_dib_1.apply_dc(hwnd);
InvalidateRect(hwnd, NULL, 0);
break;
case IDM_OPEN:
ofn.Flags = OFN_FILEMUSTEXIST;
if (!GetOpenFileName(&ofn)) break;
gt_dib_1.load_dib(filename);
gt_dib_1.apply_dc(hwnd);
gt_dib_1.apply_palette_all();
InvalidateRect(hwnd, NULL, 1);
break;
case IDM_SAVE_DIB:
ofn.Flags = 0;
if (!GetSaveFileName(&ofn)) break;
gt_dib_1.save_dib(filename);
break;
case IDM_COL:
cc.lStructSize = sizeof (CHOOSECOLOR);
cc.hwndOwner = hwnd;
cc.rgbResult = color;
cc.lpCustColors = col_costom;
cc.Flags = CC_FULLOPEN | CC_RGBINIT;
if (!ChooseColor(&cc)) break;
color = cc.rgbResult;
r = GetRValue(color);
g = GetGValue(color);
b = GetBValue(color);
// パレット
col_index = 0;
switch(gt_dib_1.m_bit_count) {
case 1 : gt_dib_1.m_col_table.get_col_index<1>(r,g,b); break;
case 4 : gt_dib_1.m_col_table.get_col_index<4>(r,g,b); break;
case 8 : gt_dib_1.m_col_table.get_col_index<8>(r,g,b); break;
}
gt_dib_1.apply_palette_all();
break;
}
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
HDC hdc;
PAINTSTRUCT ps;
static POINT mou_po, po_array[4];
static int mou_down=0;
static char s[50];
RECT rc;
int y;
HRGN hrgn, hrgn2;
switch (msg) {
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
if (gt_dib_1.m_hdc){
BitBlt( hdc, 20, 20, gt_dib_1.m_width, gt_dib_1.m_height, gt_dib_1.m_hdc, 0, 0, SRCCOPY);
}
sprintf(s, " ヨコ %d X タテ %d %dビット",
gt_dib_1.m_width, gt_dib_1.m_height, gt_dib_1.m_bit_count);
GetClientRect(hwnd , &rc);
rc.top=gt_dib_1.m_height+20;
DrawText(hdc, s, -1, &rc, DT_WORDBREAK );
EndPaint(hwnd, &ps);
break;
case WM_COMMAND:
on_command(hwnd, msg, wp, lp);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_LBUTTONDOWN:
if (!mou_down){
GetCursorPos(&start_po);
ScreenToClient(hwnd, &start_po);
mou_down=1;
}
break;
case WM_LBUTTONUP:
if (mou_down){
mou_down=0;
GetCursorPos(&end_po);
ScreenToClient(hwnd, &end_po);
gt_dib_1.draw_line(start_po.x-20, start_po.y-20, end_po.x-20, end_po.y-20, r, g, b, 255);
InvalidateRect(hwnd, NULL, 1);
}
mou_down=0;
break;
case WM_MOUSEMOVE:
if (mou_down){
hdc=GetDC(hwnd);
GetClientRect(hwnd , &rc);
if (mou_down==2){
po_array[0] = po_array[3] = start_po;
po_array[1] = po_array[2] = mou_po;
po_array[2].x++; po_array[3].x++;
po_array[2].y++; po_array[3].y++;
hrgn = CreatePolygonRgn(po_array , 4 , WINDING);
SelectObject(hdc, hrgn);
PatBlt(hdc, 0, 0, rc.right, rc.bottom, PATINVERT);
DeleteObject(hrgn);
}
mou_down=2;
GetCursorPos(&mou_po);
ScreenToClient(hwnd, &mou_po);
po_array[0] = po_array[3] = start_po;
po_array[1] = po_array[2] = mou_po;
po_array[2].x++; po_array[3].x++;
po_array[2].y++; po_array[3].y++;
hrgn2 = CreatePolygonRgn(po_array , 4 , WINDING);
SelectObject(hdc, hrgn2);
PatBlt(hdc, 0, 0, rc.right, rc.bottom, PATINVERT);
DeleteObject(hrgn2);
ReleaseDC(hwnd, hdc);
}
break;
case WM_CREATE:
ofn.lStructSize = sizeof (OPENFILENAME);
ofn.hwndOwner = hwnd;
ofn.lpstrFilter =
TEXT("bmp files {*.bmp}\0*.bmp\0")
TEXT("All files {*.*}\0*.*\0\0");
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 0;
ofn.lpstrFile = filename;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_FILEMUSTEXIST;
gt_dib_1.create(201, 151, 24, 0);
gt_dib_1.apply_dc(hwnd);
break;
}
return DefWindowProc(hwnd, msg, wp, lp);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow) {
HWND hwnd;
MSG msg;
WNDCLASS winc;
winc.style = CS_HREDRAW | CS_VREDRAW;
winc.lpfnWndProc = WndProc;
winc.cbClsExtra = winc.cbWndExtra = 0;
winc.hInstance = hInstance;
winc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winc.hCursor = LoadCursor(NULL, IDC_ARROW);
winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
winc.lpszMenuName = TEXT("GT_DIB_MENU");
winc.lpszClassName = TEXT("GT_IMG");
if (!RegisterClass(&winc)) return 1;
hwnd = CreateWindow(
TEXT("GT_IMG"), TEXT("直線描画"), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, 300, 250,
NULL, NULL, hInstance, NULL
);
if (hwnd == NULL) return 1;
while (GetMessage(&msg, NULL, 0, 0 )) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
|