Chào mừng đến với Diễn đàn lập trình - Cộng đồng lập trình.
Kết quả 1 đến 8 của 8
  1. #1
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Lại một câu hỏi về API, sướng quá [IMG]images/smilies/clap_grin.gif[/IMG]
    Cũng phức tạp đấy (ít nhất là khó hơn VB [IMG]images/smilies/lick.gif[/IMG]). Mà bạn đổi màu của button để làm j`?? màu mặc định của nó cũng đẹp đấy mà [IMG]images/smilies/biggrin.png[/IMG]. Nói vậy thôi chứ bạn cũng có thể thay màu bằng cách sau:

    1. Lúc Create cái button đó ra bạn cho nó thuộc tính BS_BS_OWNERDRAW, với thuộc tính này bạn có thể làm bất cứ cái j` trên đó (như vẽ một bitmap, một đường thẳng hay đổi màu của nó chẳng hạn [IMG]images/smilies/laughing.gif[/IMG])

    2. Trong vòng lặp xử lý sự kiện bạn bắt sự kiện WM_DRAWITEM, với sự kiện này thì có các tham số wParam là ID của cái đối tượng đó (cụ thể trong trường hợp này là cái button của mình) và lParam trỏ tới một cấu trúc DRAWITEMSTRUCT, cấu trúc này như sau:


    Mã:
    typedef struct tagDRAWITEMSTRUCT {      UINT  CtlType;     UINT  CtlID;  /* ID */    UINT  itemID;     UINT  itemAction;     UINT  itemState;     HWND  hwndItem;  /* WND của cái button */    HDC   hDC; /* DC --> cái này quan trọng */    RECT  rcItem; /* Tọa độ */    DWORD itemData; } DRAWITEMSTRUCT;
    Ok thế là đủ về lý thuyết rồi, code cụ thể sẽ như sau


    Mã:
     case WM_DRAWITEM:         if (wParam == IDC_BUTTON1) /* Nếu đúng là cái button ta đang cần tô màu */         {             HDC hdc;             RECT rc;              rc = ((LPDRAWITEMSTRUCT) lParam)->rcItem; /* Lấy tọa độ */             hdc = ((LPDRAWITEMSTRUCT) lParam)->hDC; /* Lấy DC */              HBRUSH color = CreateSolidBrush(RGB(255,100,255)); /* Tạo một bút vẽ với màu đã chọn để làm màu nền */             FillRect(hdc, &rc, color); /* Tô lên button đến đây thì chữ vẫn chưa được vẽ lên button nha */             DeleteObject(color); /* Vẽ xong rồi thì có thể bẻ ngòi bút đó đi được rồi :D */              UINT state=((LPDRAWITEMSTRUCT) lParam)->itemState;  /* Lấy trạng thái của button */               if((state & ODS_SELECTED)) /* Nếu bấm vào rồi */                 DrawEdge(hdc, &rc, EDGE_SUNKEN, BF_RECT); /* Vẽ một vòng bao ngoài làm ta có cảm giác nó đã bị lún xuống */             else                 DrawEdge(hdc, &rc, EDGE_RAISED, BF_RECT); /* Vẽ vòng bao ngoài bình thường */              SetBkColor(hdc, RGB(100,100,255)); /* Màu nền của chữ */             SetTextColor(hdc, RGB(255,0,0)); /* Màu chữ */              TCHAR buffer[MAX_PATH]; /* Chứa caption của button */             ZeroMemory(buffer,MAX_PATH ); /* Khỏi giải thích */             GetWindowText(((LPDRAWITEMSTRUCT) lParam)->hwndItem,buffer,MAX_PATH); /* Lấy caption của nó */             DrawText(hdc, buffer, lstrlen(buffer), &rc, DT_CENTER|DT_VCENTER|DT_SINGLELINE); /* Vẽ caption */         }        break;
    Đoạn code này mình build ở chế độ unicode, nếu ko bạn thay TCHAR bằng char là được.

  2. #2
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    í anh hiểu nhầm rồi [IMG]images/smilies/biggrin.png[/IMG]



    Ý của em là mỗi khi bấm 1 trong 3 cái nút ấy thì màu nền của window đổi theo. Sử dụng WM_COMMAND nhưng chưa biết dùng hàm nào để làm việc này [IMG]images/smilies/Cry.gif[/IMG]

  3. #3
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Thế à, sorry nhá, nếu như vậy thì có dễ hơn tí [IMG]images/smilies/biggrin.png[/IMG]
    Bắt sự kiện WM_ERASEBKGND, sự kiện này được gửi tới window lúc nó bị "xóa" nền. Bạn có thể tạo 1 biến kiểu static (biến iColor chẳng hạn) để lưu trạng thái nút (ví dụ khi click vào nút Red thì iColor = 1; khi click Green thì iColor = 2, ....). Chỗ này bạn bắt sự kiện WM_COMMAND để set nó.
    Trong sự kiện WM_ERASEBKGND thì xử lý như sau: nếu iColor = 1 thì tô window màu đỏ, iColor = 2 thì tô Green, ...). Cụ thể như sau:


    Mã:
    case WM_ERASEBKGND:{    RECT rc;    HBRUSH hBrush;     if (iColor == 1) /* Red */        hBrush = CreateSolidBrush(RGB(255, 0, 0));    else if (iColor ==  2)        hBrush = CreateSolidBrush(RGB(0, 255, 0));    /* .............. */    GetClientRect(hWnd, &rc);    FillRect((HDC) wParam, &rc, hBrush);    DeleteObject(hBrush);}break;
    Đó cũng chỉ là 1 cách, bạn có thể tìm hiểu thêm các cách khác nữa [IMG]images/smilies/biggrin.png[/IMG]
    Nói tóm lại là WinAPI muôn năm [IMG]images/smilies/clap_grin.gif[/IMG][IMG]images/smilies/opacli.gif[/IMG]

  4. #4
    Em làm được rồi ! [IMG]images/smilies/biggrin.png[/IMG]

    Mã:
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){    RECT rect;    HBRUSH hBrush;    static UINT buttonState;     switch(message) {    case WM_CREATE:        CreateWindow("BUTTON", "Red", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,            50, 50, 100, 50, hwnd, (HMENU)IDB_RED, ((LPCREATESTRUCT)lParam)->hInstance, NULL);        CreateWindow("BUTTON", "Green", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,            200, 50, 100, 50, hwnd, (HMENU)IDB_GREEN, ((LPCREATESTRUCT)lParam)->hInstance, NULL);        CreateWindow("BUTTON", "Blue", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,            350, 50, 100, 50, hwnd, (HMENU)IDB_BLUE, ((LPCREATESTRUCT)lParam)->hInstance, NULL);        return 0;     case WM_COMMAND:        GetClientRect(hwnd, &rect);        switch (LOWORD(wParam)) {        case IDB_RED :            buttonState = IDB_RED;            InvalidateRect(hwnd, &rect, TRUE);            break;        case IDB_GREEN :            buttonState = IDB_GREEN;            InvalidateRect(hwnd, &rect, TRUE);            break;        case IDB_BLUE :            buttonState = IDB_BLUE;            InvalidateRect(hwnd, &rect, TRUE);            break;        }        return 0;      case WM_ERASEBKGND:        switch (buttonState) {        case IDB_RED : hBrush = CreateSolidBrush(RGB(255, 0, 0));            break;        case IDB_GREEN : hBrush = CreateSolidBrush(RGB(0, 255, 0));            break;        case IDB_BLUE : hBrush = CreateSolidBrush(RGB(0, 0, 255));            break;        }        GetClientRect(hwnd, &rect);        FillRect((HDC)wParam, &rect, hBrush);        DeleteObject(hBrush);        return 0;     case WM_DESTROY:        PostQuitMessage(0);        return 0;    }    return DefWindowProc(hwnd, message, wParam, lParam);}
    Nhưng lại có thêm vấn đề căn vị trí control khi kích thước windows thay đổi ? Em phải làm thế nào ?
    Làm cách nào để 3 cái button luôn luôn ở chính giữa form khi kích thước thay đổi ?
    [IMG]images/smilies/dont_know.gif[/IMG]


    vui lòng dùng font chữ vừa phải nha bạn

  5. #5
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Chúc mừng nhé! [IMG]images/smilies/biggrin.png[/IMG]
    Còn vấn đề canh các control cho nó nằm chính giữa thì bàn nhiều rồi, bạn có thể làm như sau: Bắt sự kiện WM_SIZE, sự kiện này được gửi đến window khi kích thước bị thay đổi. Bạn có thể dùng các hàm API và các phép toán để canh control cho đúng. Giới thiệu cho bạn một số hàm:
    GetClientRect(HWND, LPRECT); /* Lấy tọa độ vùng làm việc của form */
    MoveWindow(HWND, X, Y, Width, Height, RePaint); /* Di chuyển 1 cửa sổ hoặc 1 control */
    GetWindowRect(HWND, LPRECT); /* Lấy tọa độ của window (control) */
    và một vài hàm nữa [IMG]images/smilies/biggrin.png[/IMG] nếu cần hỏi bạn cứ post lên đây [IMG]images/smilies/smile.png[/IMG]

  6. #6
    Ngày tham gia
    Sep 2015
    Bài viết
    0

    Thay đổi màu sắc của background như thế nào?

    Em có một form như sau


    Đây là WinProc hiện nay :
    Mã nguồn PHP:
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; RECT rect; switch(message) { case WM_CREATE: CreateWindow("BUTTON", "Red", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 50, 50, 100, 50, hwnd, (HMENU)IDB_RED, ((LPCREATESTRUCT)lParam)->hInstance, NULL); CreateWindow("BUTTON", "Green", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 200, 50, 100, 50, hwnd, (HMENU)IDB_GREEN, ((LPCREATESTRUCT)lParam)->hInstance, NULL); CreateWindow("BUTTON", "Blue", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 350, 50, 100, 50, hwnd, (HMENU)IDB_BLUE, ((LPCREATESTRUCT)lParam)->hInstance, NULL); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); GetClientRect(hwnd, &rect); DrawText(hdc, "Hello Windows", -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }  
    Em phải thêm gì vào WM_PAINT để thay đổi màu background khi click 1 trong 3 cái nút trên ? Ngoài ra em phải sử dụng thêm event nào ?

  7. #7
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    em mới hoc API, mấy bác pro vho em hoi~ tại sao trong hàm FillRect((HDC)wParam, &rect, hBrush); lại dùng tham số (HDC)wParam. khi em tra nó bảo tham sô thứ 1 là handle của device context.mà từ này dịch ra ko hiểu.mong cac bạn giai thích ro~ thêm,thank nhiều

  8. #8
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Lập trình đồ họa bằng GDI trong windows thì mọi thao tác vẽ đều phải thông qua Device Context, cứ tưởng tượng (tưởng tượng thôi nha) Device Context (DC) là tờ giấy ~> phải vẽ lên tờ giấy chứ vẽ lên không khí thì đâu thấy gì. Mỗi DC được windows gán cho 1 ID và cái ID này được gọi là Handle of Device Context - là kiểu HDC đó (tui cũng ko biết dịch thế nào nữa).

 

 

Quyền viết bài

  • Bạn Không thể gửi Chủ đề mới
  • Bạn Không thể Gửi trả lời
  • Bạn Không thể Gửi file đính kèm
  • Bạn Không thể Sửa bài viết của mình
  •