我自己创建了一个画刷,比如是蓝色的,然后随便画了一条蓝色线段m1(50,60)m2(50,100),为什么我使用GetPixel(hdc,50,70)获取该线段上的颜色值本应是255,为什么却是4294967295。
部分代码如下:
hdc = GetDC(hwnd);
        HPEN hpen = CreatePen(PS_SOLID,1,RGB(0,0,255));
        HPEN old_hpen = (HPEN)SelectObject(hdc,hpen);       // move to a  postion
       MoveToEx(hdc, 50,60, NULL);       // draw a line
       LineTo(hdc,50, 100);
      COLORREF color1=GetPixel(hdc,50,70);//调试时得不到正确结果
       // now delete the pen
       SelectObject(hdc,old_hpen);
       DeleteObject(hpen);
    
       // release the device context
       ReleaseDC(hwnd,hdc);
请问我应该怎样准确获得该线段上像素点的颜色值?多谢!

解决方案 »

  1.   

    COLORREF 得结构定义事 0x00rrggbb  ,16进制COLORREF color1=GetPixel(hdc,50,70);
    红色 unsigned char red=0x00ff0000 & color1;
    蓝色 unsigned char blue=0x0000ff00 & color1;
    绿色 unsigned char green=0x000000ff & color1;
      

  2.   

    你试着把断点设置在GetPixel之后,因为如果是在之前,窗口变了,你指定的位置的像素就不是原来的了,所以颜色不对了。
      

  3.   

    很简单啊!
    有三个宏可以得到颜色值:
    BYTE GetGValue(DWORD rgb):取得绿色值;
    BYTE GetRValue(DWORD rgb):取得红色值;
    BYTE GetBValue(DWORD rgb):取得蓝色值;
    其中rgb就你调用GetPixel的反回值。
      

  4.   

    颜色值4294967295, 即0xffffffff,采用GetBValue(color1),当然得到的是蓝色分量了。我现在要得到的不是三元色分量,而是准确的COLORREFR的值0x00bbggrr。
     我的断点是设在SelectObject(hdc,old_hpen),GetPixel()和LineTo()都使用逻辑坐标。
      

  5.   

    // INCLUDES ///////////////////////////////////////////////
    #define WIN32_LEAN_AND_MEAN  // just say no to MFC
    #include <windows.h>   // include all the windows headers
    #include <windowsx.h>  // include useful macros
    #include <stdio.h>
    #include <stdlib.h>
    // defines for windows 
    #define WINDOW_CLASS_NAME "WINCLASS1"
    #define WINDOW_WIDTH  400
    #define WINDOW_HEIGHT 300// GLOBALS ////////////////////////////////////////////////
    HWND      main_window_handle = NULL; // globally track main window
    HINSTANCE hinstance_app      = NULL; // globally track hinstance
    // FUNCTIONS //////////////////////////////////////////////
    LRESULT CALLBACK WindowProc(HWND hwnd, 
        UINT msg, 
                                WPARAM wparam, 
                                LPARAM lparam)
    {
    // this is the main message handler of the system
    HDC hdc; // handle to a device context// what is the message 
    switch(msg)
    {
    case WM_DESTROY: 
    {
    PostQuitMessage(0);
    return(0);
    } break;
    default:break;
        } // end switch// process any messages that we didn't take care of 
    return (DefWindowProc(hwnd, msg, wparam, lparam));
    } // end WinProc// WINMAIN ////////////////////////////////////////////////
    int WINAPI WinMain( HINSTANCE hinstance,
    HINSTANCE hprevinstance,
    LPSTR lpcmdline,
    int ncmdshow)
    {WNDCLASSEX winclass; // this will hold the class we create
    HWND    hwnd;  // generic window handle
    MSG    msg;  // generic message
    //HDC        hdc;      // graphics device context// first fill in the window class stucture
    winclass.cbSize         = sizeof(WNDCLASSEX);
    winclass.style = CS_DBLCLKS | CS_OWNDC | 
                              CS_HREDRAW | CS_VREDRAW;
    winclass.lpfnWndProc = WindowProc;
    winclass.cbClsExtra = 0;
    winclass.cbWndExtra = 0;
    winclass.hInstance = hinstance;
    winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    winclass.hCursor = LoadCursor(NULL, IDC_ARROW); 
    winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    winclass.lpszMenuName = NULL;
    winclass.lpszClassName = WINDOW_CLASS_NAME;
    winclass.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);// save hinstance in global
    hinstance_app = hinstance;// register the window class
    if (!RegisterClassEx(&winclass))
    return(0);
    // create the window
    if (!(hwnd = CreateWindowEx(NULL,                // extended style
                                WINDOW_CLASS_NAME,   // class
        "Drawing Line Demo", // title
        WS_OVERLAPPEDWINDOW | WS_VISIBLE,
          0,0,   // initial x,y
        WINDOW_WIDTH, // initial width
                                WINDOW_HEIGHT,// initial height
        NULL,   // handle to parent 
        NULL,   // handle to menu
        hinstance,// instance of this application
        NULL))) // extra creation parms
    return(0);// save main window handle
    main_window_handle = hwnd;
    while(GetMessage(&msg,NULL,0,0))
    {
    // translate any accelerator keys
    TranslateMessage(&msg);
    // send the message to the window proc
    DispatchMessage(&msg);   
    // get the graphics device context 
        HDC hdc = GetDC(hwnd);
        HPEN hpen = CreatePen(PS_SOLID,1,RGB(0,0,255));
        HPEN old_hpen = (HPEN)SelectObject(hdc,hpen);
        // move to a  postion
        MoveToEx(hdc, 50,60, NULL);
        // draw a line
        LineTo(hdc,50, 100);
        COLORREF color1=GetPixel(hdc,50,70);//调试时得不到正确结果
        // now delete the pen
        SelectObject(hdc,old_hpen);
        DeleteObject(hpen);    
        // release the device context
        ReleaseDC(hwnd,hdc);} // end while
    // return to Windows like this
    return(msg.wParam);
    } // end WinMain
      

  6.   

    “准确的COLORREFR的值0x00bbggrr”楼主是怎么算的?
      

  7.   

    0x00ff0000是不是就是4294967295。
      

  8.   

    swimmingfish2004:
       引自MSDN
    The COLORREF value is a 32-bit value used to specify an RGB color. Res
    When specifying an explicit RGB color, the COLORREF value has the following hexadecimal form: 0x00bbggrr 
      

  9.   

    4294967295是0xffffffff。我用计算器算过,正好是2的32次方减1。
      

  10.   

    知道了就是断点的问题,你将断点设在GetPixel之后就对了,一定要在之后
      

  11.   

    HPEN old_hpen = (HPEN)SelectObject(hdc,hpen);
        // move to a  postion
        MoveToEx(hdc, 50,60, NULL);
        // draw a line
        LineTo(hdc,50, 100);
        COLORREF color1=GetPixel(hdc,50,70);//调试时得不到正确结果
    断点设在SelectObject,那样的话当你调用GetPixel时,得到的不是你的EXE的窗口的像素值,因为他已经最小化了,而且不是当前的窗口,所以程序中断必须在GetPixel之后,故断点要设在之后,这样值就对了。
      

  12.   

    swimmingfish2004:
       我把断点是设在 SelectObject(hdc,old_hpen)一行上的。
    我已发了完整的代码,请朋友们调试一下看看。点(50,70)明明在蓝色线段上,为什么就得不到蓝色的颜色值?
      

  13.   

    楼主真强!第一次看到在“while(GetMessage(&msg,NULL,0,0))”循环里绘制界面的。开了眼界了。你不能把这点代码放到WM_PAINT消息里吗?
      

  14.   

    好说得还有正确 swimmingfish2004(something) 如 Mackz(在相互)  说:
      绘制界面-》WM_PAINT
      

  15.   

    Mackz:
       你就别笑我了。
       放在循环里面是有问题。窗口是黑色背景,则每重新绘制一次得到的也不是白色,而是蓝色。我依你所说,重新改了代码,把绘制部分放入WM_PAINT消息中,可得到的结果仍然是先是color1=0(正确),然后是=4294967295(误)。
    改后的代码如下:
    #include <windows.h>   // include all the windows headers
    #include <windowsx.h>  // include useful macros
    #include <stdio.h>
    #include <stdlib.h>
    // defines for windows 
    #define WINDOW_CLASS_NAME "WINCLASS1"
    #define WINDOW_WIDTH  400
    #define WINDOW_HEIGHT 300// GLOBALS ////////////////////////////////////////////////
    HWND      main_window_handle = NULL; // globally track main window
    HINSTANCE hinstance_app      = NULL; // globally track hinstance
    // FUNCTIONS //////////////////////////////////////////////
    LRESULT CALLBACK WindowProc(HWND hwnd, 
        UINT msg, 
                                WPARAM wparam, 
                                LPARAM lparam)
    {
    // this is the main message handler of the system
    HDC hdc; // handle to a device context
    HPEN hpen;
    HPEN old_hpen;
    COLORREF color1;// what is the message 
    switch(msg)
    {
    case WM_PAINT:
    // get the graphics device context 
        hdc = GetDC(hwnd);
        hpen = CreatePen(PS_SOLID,1,RGB(0,0,255));
        old_hpen = (HPEN)SelectObject(hdc,hpen);
    color1=GetPixel(hdc,50,70);
        // move to a  postion
        MoveToEx(hdc, 50,60, NULL);
        // draw a line
        LineTo(hdc,50, 100);
        color1=GetPixel(hdc,50,70);//调试时得不到正确结果
        // now delete the pen
        SelectObject(hdc,old_hpen);
        DeleteObject(hpen);    
        // release the device context
        ReleaseDC(hwnd,hdc);
    return (0);
    break;
    case WM_DESTROY: 
    {
    PostQuitMessage(0);
    return(0);
    } break;
    default:break;
        } // end switch// process any messages that we didn't take care of 
    return (DefWindowProc(hwnd, msg, wparam, lparam));
    } // end WinProc// WINMAIN ////////////////////////////////////////////////
    int WINAPI WinMain( HINSTANCE hinstance,
    HINSTANCE hprevinstance,
    LPSTR lpcmdline,
    int ncmdshow)
    {WNDCLASSEX winclass; // this will hold the class we create
    HWND    hwnd;  // generic window handle
    MSG    msg;  // generic message
    //HDC        hdc;      // graphics device context// first fill in the window class stucture
    winclass.cbSize         = sizeof(WNDCLASSEX);
    winclass.style = CS_DBLCLKS | CS_OWNDC | 
                              CS_HREDRAW | CS_VREDRAW;
    winclass.lpfnWndProc = WindowProc;
    winclass.cbClsExtra = 0;
    winclass.cbWndExtra = 0;
    winclass.hInstance = hinstance;
    winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    winclass.hCursor = LoadCursor(NULL, IDC_ARROW); 
    winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    winclass.lpszMenuName = NULL;
    winclass.lpszClassName = WINDOW_CLASS_NAME;
    winclass.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);// save hinstance in global
    hinstance_app = hinstance;// register the window class
    if (!RegisterClassEx(&winclass))
    return(0);
    // create the window
    if (!(hwnd = CreateWindowEx(NULL,                // extended style
                                WINDOW_CLASS_NAME,   // class
        "Drawing Line Demo", // title
        WS_OVERLAPPEDWINDOW | WS_VISIBLE,
          0,0,   // initial x,y
        WINDOW_WIDTH, // initial width
                                WINDOW_HEIGHT,// initial height
        NULL,   // handle to parent 
        NULL,   // handle to menu
        hinstance,// instance of this application
        NULL))) // extra creation parms
    return(0);// save main window handle
    main_window_handle = hwnd;
    while(GetMessage(&msg,NULL,0,0))
    {
    // translate any accelerator keys
    TranslateMessage(&msg);
    // send the message to the window proc
    DispatchMessage(&msg);   
    } // end while
    // return to Windows like this
    return(msg.wParam);
    } // end WinMain
      

  16.   

    你是在调试时候看的?那个时候程序中断,可能得不到正确的值,用TRACE或者MessageBox看看结果。    color1=GetPixel(hdc,50,70);//调试时得不到正确结果
        char *pText = new char[20];
        sprintf(pText, "%x", color1);
        TextOut(hdc, 0, 0, pText, lstrlen(pText));
        delete []pText;
      

  17.   

    Mackz:
        依你上面所写的代码,添加进去后,窗口中出现正确结果ff0000。
    但我不明白两个问题:1)为什么程序中断时,不能得到正确值?
    2)输出的结果ff0000值总在闪烁,程序在循环执行WM_PAINT消息吗?
    呵呵,今天是周末,小菜在这里多谢大家了!