• ベストアンサー

色描画

以下は、ウインドウプロシージャ内でのプログラムです。 RGB( )ですが、0xFFは、255の事ですよね? x*0xFF/rect.rightこの計算式は、何を求めているんですか? 教えてください。 HDC         hdc; PAINTSTRUCT  ps; COLORREF    color; LONG        x,y; RECT        rect; switch(umsg){   case  WM_PAINT:       hdc =BeginPaint(hwnd,&ps);       GetClientRect(hwnd,&rect);       for(y=0;y<rect.bottom;y++){          for(x=0;x<rect.right;x++){            color=RGB(x*0xFF/rect.right,0,0);            SetPixel(hdc,x,y,color);          }       }

noname#168725
noname#168725

質問者が選んだベストアンサー

  • ベストアンサー
  • koedame
  • ベストアンサー率33% (10/30)
回答No.2

最初の方のとおりです。 %で考えるとわかりやすいかもしれません。 >color=RGB(x*0xFF/rect.right,0,0); のように記述してありますが、 color=RGB(0xFF*(x/rect.right),0,0); と見た方がいいでしょう。 for 文では x は rect.right よりは大きくはなりません。 つまり   x ---------- × 100 = 0~99.・・・% rect.right となります。 x が大きいほど(右の方ほど)%が100に 近いので 0xFF に近くなり白色になる x が小さいほど(左の方ほど)%が0に 近いので0x00 に近くなり黒色になる 0xFF(白(255)) × 0 ~ 1(だいたい) = ~~~ みたいな感じですね。 色が間違っていたらすみません。 まあ、考えとしてはそんな感じです。

noname#168725
質問者

お礼

すばやい回答ありがとうございます! どうもありがとうございました!

その他の回答 (1)

  • yosi_yosi
  • ベストアンサー率35% (165/468)
回答No.1

x * 0xFF / rect.right は式を置き換えれば、 0xFF * (x / rect.right) となります。 画面の左端(X=0)では式の値は0となり黒で、右端(rect.right)では0xFF(=255)となり輝度が最大(赤)となります。 つまり横方向に変化する赤色のグラデーションを描いているわけです。 それで最初の順番に並んでいるのにも深い理由があります。 それは全ての値が整数値であることです。 0xFF * (x / rect.right) をそのまま記述すると、x!=rect.rightでは 0xFF * 0 となってしまいます。 それを防ぐために計算の順番を置き換えています。

noname#168725
質問者

お礼

すばやい回答ありがとうございます! 参考になりました!

関連するQ&A

  • C言語で画面がおかしくなる

    最近C言語でプログラムを書き始めました。 二次関数を作るスクリプトなんですが、一定時間がたつと画面がおかしくなります。 どこが問題なのか探しても見つからないので、わかる方教えてください。 WinMainの部分は省いてます #include<windows.h> #include<stdio.h> #include <stdlib.h> #include<time.h> #define TIMER_ID 1 #define spy(num) (wy-num) int rnd(int r); void bset(HDC hdc, int x, int y); LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) { HDC hDC; static int DesktopX ,DesktopY; static HDC hdc; static HDC Mhdc; static HBITMAP BMPhdc; PAINTSTRUCT paint; RECT Rect; LOGPEN lopnPen; POINT CursorP, ScreenP; char str[250]; int i; static int wx, wy ,ky; static double a ,b ,c ,x ,y ,n ,m ,s ,t; switch (msg) { case WM_DESTROY: DeleteObject( BMPhdc ); DeleteDC( Mhdc ); PostQuitMessage(0); return 0; case WM_CREATE: SetTimer(hwnd, TIMER_ID, 10, NULL); hDC = GetDC(hwnd); hdc = CreateCompatibleDC( hDC ); GetClientRect(GetDesktopWindow() ,&Rect); DesktopX = Rect.right ;DesktopY = Rect.bottom; BMPhdc = CreateCompatibleBitmap( hDC, DesktopX, DesktopY ); SelectObject( hdc, BMPhdc ); ReleaseDC( hwnd, hDC ); GetClientRect(hwnd, &Rect); wx = Rect.right ;wy = Rect.bottom; x = rnd(wx); y = rnd(wy); n = rnd(wx); m = rnd(wy); return 0; case WM_TIMER: ScreenP.x = LOWORD(lp); ScreenP.y = HIWORD(lp); GetClientRect(hwnd, &Rect); wx = Rect.right ;wy = Rect.bottom; if( ky == 1 ){ x = rnd(wx); y = rnd(wy); n = rnd(wx); m = rnd(wy); } ClientToScreen(hwnd ,&ScreenP); GetCursorPos(&CursorP); s = CursorP.x-ScreenP.x; t = wy-(CursorP.y-ScreenP.y); InvalidateRect(hwnd, NULL, FALSE); return 0; case WM_RBUTTONDOWN: ky = 1; return 0; case WM_RBUTTONUP: ky = 0; return 0; case WM_PAINT: Mhdc = BeginPaint(hwnd, &paint); SelectObject(hdc , CreateSolidBrush(RGB(255,255,255))); lopnPen.lopnStyle = PS_NULL; SelectObject(hdc , CreatePenIndirect(&lopnPen)); Rectangle(hdc , 0 , 0 , wx+1 , wy+1); SelectObject(hdc , CreateSolidBrush(RGB(255,0,0))); if ((s-n) != 0 && (n-x) != 0 && (s-x) != 0){ a = ((t-m)/(s-n) - (m-y)/(n-x)) / (s-x); b = (m-y)/(n-x) - a*(n+x); c = y - a*x*x -b*x; } bset(hdc, x,spy(y)); bset(hdc, n,spy(m)); bset(hdc, s,spy(t)); lopnPen.lopnStyle = PS_SOLID; lopnPen.lopnColor = RGB(0,0,255); SelectObject(hdc , CreatePenIndirect(&lopnPen)); MoveToEx(hdc , -1 , spy( a + b - c) , NULL); for(i = 0 ; i <= wx ;i++){ LineTo(hdc , i , spy( a*i*i - b*i - c)); } BitBlt(Mhdc, 0, 0, DesktopX, DesktopY, hdc, 0, 0, SRCCOPY ); EndPaint(hwnd, &paint); return 0; } return DefWindowProc(hwnd , msg , wp , lp); } int rnd(int r){ static int flag; if (flag == 0) { srand((unsigned int)time(NULL)); flag = 1; } return (int)(rand()*(r+1.0)/(1.0+RAND_MAX)); } void bset(HDC hdc, int x, int y){ static LOGPEN lopnPen; lopnPen.lopnStyle = PS_NULL; SelectObject(hdc , CreatePenIndirect(&lopnPen)); Rectangle(hdc , x-3 , y-3 , x+3 , y+3); return; }

  • SDKでウィンドウの中央に文字列を表示させる方法

    ウィンドウの中央に文字列sを表示させる方法を教えて下さい。 /********************************** WM_PAINTで TCHAR s[80]; HDC hDC; PAINTSTRUCT ps; RECT rc; GetClientRect(hWnd, &rc); hDC = BeginPaint(hWnd, &ps); TextOut(hDC, rc.right / 2, rc.bottom / 2, tcDayTime, lstrlen(s)); EndPaint(hWnd, &ps); return FALSE; ***********************************/ GetClientRect(hWnd, &rc);でウィンドウのサイズを取得し、 TextOutの第2、第3引数で ウィンドウ幅/2、ウィンドウ高さ/2 としていますが、これだと中央から表示されてしまいます。 できれば、ウィンドウのサイズを変更してもウィンドウの中央に表示させたいです。 #VC ++ 6.0 & Win98 & SDK で作成してます。

  • OpenGLでウィンドウハンドルの取得

    コンソールアプリで作ることが前提です。 glut関数で作成したウィンドウのハンドルを取得し、その画面上に文字を表示しようとTextOutやDrawTextやらを使ってみたんですが、背景色しか表示されません。DrawTextの戻り値が18だったので成功していると思うのですが。どこがおかしいのかご指摘をお願いします。 #include<stdio.h> #include<windows.h> #include<GL/glut.h> HWND hwnd; void display(){ glClearColor(0.5,0.5,0.5,1); glClear(GL_COLOR_BUFFER_BIT); hwnd=GetActiveWindow(); PAINTSTRUCT ps; HDC hdc; RECT rect; LPCSTR str = TEXT("あああ"); GetClientRect(hwnd, &rect); hdc = BeginPaint(hwnd, &ps); SetRect( &rect, 10, 10, 100, 100); TextOut(hdc, 10, 10, str, lstrlen(str));    DrawText(hdc, TEXT("あああ"), -1, &rect,DT_CENTER); EndPaint(hwnd, &ps); glFlush(); } int main(int argc,char **argv){ glutInit(&argc,argv); glutInitWindowSize(640,480); glutCreateWindow("aaa"); glutDisplayFunc(display); glutMainLoop(); return(0); }

  • 点の描画について(win32API)

    win32APIでウィンドウに点を描画するプログラムを作ったのですが、SetPixel関数で点を描画しようとすると、特定のx座標に点が描画されません。線は普通に描画されるのですが・・・。 /*ソース*/ #include <windows.h> LRESULT CALLBACK WndProc(HWND hwnd, UINT Msg, WPARAM wp, LPARAM lp) { static HDC hdc; static PAINTSTRUCT ps; switch(Msg) { case WM_PAINT: //【ここです!】 hdc = BeginPaint(hwnd, &ps); MoveToEx(hdc , 0 , 300 , NULL); //比較のため線を引く準備 LineTo(hdc,1200,300); //比較のため線を引く for( int j = 1000; j > 0 ; j-- )SetPixel( hdc, j, 100, RGB(0,200,100) ) ; for( int j = 1000; j > 0 ; j-- )SetPixel( hdc, j, 200, RGB(0,200,100) ) ; //ここで点を描画 EndPaint(hwnd, &ps); return 0; case WM_DESTROY: //終了処理 PostQuitMessage(0); return 0; } return DefWindowProc( hwnd, Msg, wp, lp ); } //↓ごく普通のWinMainです。無視してください。 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 = NULL; winc.lpszClassName = TEXT("KITTY"); if (!RegisterClass(&winc)) return -1; hwnd = CreateWindow( TEXT("KITTY") , TEXT("Kitty on your lap") , WS_OVERLAPPEDWINDOW | WS_VISIBLE , CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT , NULL , NULL , hInstance , NULL ); if (hwnd == NULL) return -1; while( GetMessage(&msg , NULL , 0 , 0) ) DispatchMessage(&msg); return msg.wParam; } 解決策を模索するもうまくいかず・・・どうか回答よろしくお願いします。

  • WinAPIでRECT構造体の宣言について

    PAINTSTRUCT ps; HDC hdc; RECT rct={200,200,200,200}; char *szStr = "あけまして\n\tおめでとう"; switch (msg) { case WM_PAINT: GetClientRect(hWnd, &rct); hdc = BeginPaint(hWnd, &ps); DrawText(hdc, (LPCTSTR)szStr, -1, &rct, DT_CENTER | DT_WORDBREAK); EndPaint(hWnd, &ps); break; のようにしているのですが文字列が表示される場所が中央上部です。 何故なのでしょう? 自分としてはど真ん中辺りから表示されるようにしているつもりなのですが

  • 猫でもわかるゲームプログラミング3章

    猫でもわかるゲームプログラミング第1版を見て勉強しているプログラミング初心者です。 本に問題ありな気がします。作者にも出版社にも問い合わせメール書きましたが返事ないです。 以前の質問 setpixel01: http://okwave.jp/qa/q6349241.html polyline01: http://okwave.jp/qa/q6362229.html だったのですが、polyline01の方ではプログラム通りの多重四角が表示されたんですが、(あ、うっかりしてました。自分がコード少し間違っていて質問してしまったようでした;;)本の実行結果より図形のウィンドウがはみ出してしまっていてすっきりしない終わり方でした。 今回の問題はpolypolyline01という六芒星をウィンドウいっぱいに沢山表示するプログラムなんですが、setpixel01と同じく math.hを宣言してpow関数を使います。使うのは2とかまた簡単な数字だったんですがビルドできないので少数第一位まで表記してコンパイルしたんです。そしたら実行結果の六芒星がおかしな形で一列に表示されてしまいました。 //ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id, i, j, l = 40; HDC hdc; PAINTSTRUCT ps; RECT rc; switch (msg) { case WM_PAINT: hdc = BeginPaint(hWnd, &ps); GetClientRect(hWnd, &rc); for (i = 0; i * 60 <= rc.right; i++) { for(j = 0;j * 60 <= rc.bottom; j++){ MyDraw(hdc, 60 * i, 60 + j, l); } } EndPaint(hWnd, &ps); break; case WM_CLOSE: id = MessageBox(hWnd, "終了してもよろしいですか", "終了確認", MB_YESNO); if (id == IDYES) DestroyWindow(hWnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; } BOOL MyDraw(HDC hdc, int x, int y, int l) { POINT pt[8]; DWORD dwPoints[2] = {4, 4}, dwCount = 2; int h; h = (int)sqrt(pow(l,2.0) - pow(l / 2.0, 2.0)); pt[0].x = x; pt[0].y = y; pt[1].x = l / 2 + x; pt[1].y = h + y; pt[2].x = l + pt[0].x; pt[2].y = pt[0].y; pt[3].x = pt[0].x; pt[3].y = pt[0].y; pt[4].x = pt[0].x; pt[4].y = pt[0].y + h * 2 / 3; pt[5].x = l + pt[0].x; pt[5].y = pt[4].y; pt[6].x = l / 2 + pt[0].x; pt[6].y = y- h / 3; pt[7].x = pt[4].x; pt[7].y = pt[4].y; PolyPolyline(hdc, pt, dwPoints, dwCount); return TRUE; } なんですけど・・・ どこか数式が間違ってるんでしょうか?自分で見直す感じ見つけられません。 猫でもわかる~のソースコードがDLできるってことでしたが、ゲームプログラミングはDLできないようです。。 あとちなみにこのプログラム(polypolyline01.cpp)のCD-ROMから読んだサンプルファイルは、文字化けてました。 お分かりになる方、教えてください!

  • デバイスコンテキストの宣言に関するエラー?について

    Run-Time Check Failure #3 - The variable 'hMemDC' is being used without being defined. というエラーが出ます。 自分としては、WM_CREATEの処理で、初期化を行っているつもりなのですが・・・ 力を貸して頂ければ有難いです。よろしくお願いします。 ちなみに、関係のありそうな部分だけ掲載しています。 この部分だけ残して、他の部分をコメントアウトしてコンパイルしても、同じエラーメッセージが出ました。 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; RECT rect; HDC hDC; PAINTSTRUCT ps; HDC hMemDC; HBITMAP hMemBmp; HDC hMjDC; HBITMAP hMjBmp; BITMAP MjBmp; /* POINT posMJ; int MJshot; POINT posMJshot;*/ switch (message) { case WM_CREATE: GetClientRect(hWnd, &rect); // クライアント領域の大きさをrectに格納 hDC = GetDC(hWnd); hMemDC = CreateCompatibleDC(hDC); // hDCと互換性をとるメモリデバイスコンテキストhMemDCを構築 hMemBmp = CreateCompatibleBitmap(hMemDC, rect.right, rect.bottom); hMjDC = CreateCompatibleDC(hMemDC); // hMemDCと互換性をとるメモリデバイスコンテキストhMjDCを構築 hMjBmp = (HBITMAP)LoadImage( // ビットマップイメージMYJET(リソース)をhMjBmpに設定 (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), MAKEINTRESOURCE(IDB_MYJET), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR ); SetTimer(hWnd, 1, 10, NULL); // 100分の1秒毎にWM_TIMERメッセージを送るタイマー1をセット break; case WM_PAINT: hDC = BeginPaint(hWnd, &ps); // hDCにディスプレイのデバイスコンテキストのハンドルを格納 BitBlt( // hDCにバックバッファhMemDCを転送 hDC, 0, 0, rect.right, rect.bottom, hMemDC, 0, 0, SRCCOPY ); EndPaint(hWnd, &ps); break;

  • ActionscriptのBitmapDataの描画速度

    BitmapDataクラスを使って単色で塗りつぶしたのですが、 以下の二つの方法で試して速度を比較してみました。 1)各ピクセル毎にループさせて、setPixel(x, y, color)で各ピクセルを塗りつぶした。 2)fillRect(rect, color)で一気に塗りつぶした。 結果は、2)の方が断然速く処理しました。なぜ塗りの速度が全然違うのでしょうか?fillRectの中では何が行われているのでしょうか? ご教授願います。

    • ベストアンサー
    • Flash
  • WinAPIで画像を更新し続けるには

    本を見ながら、WindowsSDKを使ってビットマップを描画する 所まではできたのですが、動かそうとすると上手くいきません。 ソースを簡略かして載せますと、以下のようにしています。 case WM_KEYDOWN: x++; // static MyDrawBitMap( hWnd, x, 10 ); ------------------------------------------------ void MyDrawBitMap( HWND hWnd, int x, int y ) { hdc = BeginPaint(hWnd, &ps); BitBlt( hdc, x, y, bitmap.bmWidth, bitmap.bmHeight, hMemDC, 0, 0, SRCCOPY); EndPaint(hWnd, &ps); このように書いてますが、ボタンを押しても画面に変化が出ません。 PAINTSTRUCTは再描画が必要な情報に関する構造体だとは解っていま すが、特に変更の必要の無い画像も再描画したい場合の処理はどうす れば良いのでしょうか?よろしくお願いします。

  • Windowsプログラミング リージョンについて

    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { HDC hdc; PAINTSTRUCT ps; HRGN hRgn1, hRgn2; RECT rect; switch(msg){ case WM_DESTROY: PostQuitMessage(0); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); hRgn1 = CreateEllipticRgn(10, 10, 100, 100); hRgn2 = CreateEllipticRgn(50, 50, 200, 150); CombineRgn(hRgn1, hRgn1, hRgn2, RGN_OR); SelectClipRgn(hdc, hRgn1); GetClipBox(hdc, &rect); GetClipRgn(hdc, hRgn2); SelectClipRgn(hdc, NULL); DeleteObject(hRgn1); Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom); FillRgn(hdc, hRgn2, GetStockObject(BLACK_BRUSH)); DeleteObject(hRgn2); EndPaint(hwnd, &ps); return 0; } return DefWindowProc(hwnd, msg, wp, lp); } リージョンというものがよく理解できません。 なぜCombineRgnの第一引数のリージョンが存在していないといけないのですか? DeleteObject(hRgn1);でhRgn1をDeleteしてるのにhRgn2が使えるのは なぜですか?  GetClipRgnで設定されたリージョンを取得しているようなんですか、このリージョンは領域の情報の共有ではなく、たんなる 領域の情報のコピーなのですか? DeleteObjectでDeleteしているhRgn1, hRgn2はどのリージョン(どのリージョンといった方がいいのかわかりませんが)を削除しているのか分かりません。 あと上記のソースとは関係ないのですが hRgn1 = CreateEllipticRgn(10, 10, 100, 100); hRgn2 = CreateEllipticRgn(50, 50, 200, 150); CombineRgn(hRgn1, hRgn1, hRgn2, RGN_OR); DeleteObject(hRgn1); DeleteObject(hRgn2); ←もしかしてこれは不要? としたとき DeleteObject(hRgn2);は不要なのでしょうか? 超初心者な質問ですみません。質問の仕方へたですみません。 分かる人お願いします。

専門家に質問してみよう