Từ 1 tới 10 trên tổng số 10 kết quả

Đề tài: [Win32 API] Nhờ hướng dẫn Click chuột để vẽ điểm ảnh và nối các điểm

  1. #1
    Ngày gia nhập
    05 2012
    Bài viết
    12

    Mặc định [Win32 API] Nhờ hướng dẫn Click chuột để vẽ điểm ảnh và nối các điểm

    Nhờ các bác hướng dẫn giúp code đoạn này như thế nào với ạ.
    WM_RBUTTONDOWN và WM_LBUTTONDOWN thôi ạ.

    Em cảm ơn rất nhiều !

    Tạo cửa sổ với các chức năng sau:
    + Khi nhấn chuột phải thì xóa miền thao tác
    + Khi nhấn chuột trái thì vẽ điểm ảnh tại vị trí nhấn
    + Khi click đúp chuột trái thì nối các điểm đã vẽ lại với nhau như hình vẽ:
    Click vào hình ảnh để lấy hình ảnh lớn

Tên:		Untitled.jpg
Lần xem:	2
Size:		54.4 KB
ID:		55023

  2. #2
    Ngày gia nhập
    02 2014
    Nơi ở
    TP.HCM
    Bài viết
    706

    Bạn viết được tới đâu rồi đưa lên thử, tôi sẽ viết ngay cho bạn một mẫu trong khoảng 15'.

    - - - Nội dung đã được cập nhật ngày 14-06-2017 lúc 02:47 PM - - -

    C++ Code:
    1. #include<Windows.h>
    2. #include<vector>
    3. void Draw(HWND hwnd, std::vector<POINT> & vtPoints, BOOL bLines)
    4. {
    5.     size_t  cPoints = vtPoints.size();
    6.     if (!cPoints)
    7.         return;
    8.     HDC     hdc = GetDC(hwnd);
    9.     if(!bLines)
    10.         for (std::vector<POINT>::iterator i = vtPoints.begin(); i != vtPoints.end(); i++)
    11.             SetPixel(hdc, (*i).x, (*i).y, 0);
    12.     if (bLines && cPoints > 1)
    13.         for (size_t i = 0; i < cPoints - 1; i++)
    14.             for (size_t j = i + 1; j < cPoints; j++)
    15.             {
    16.                 MoveToEx(hdc, vtPoints[i].x, vtPoints[i].y, NULL);
    17.                 LineTo(hdc, vtPoints[j].x, vtPoints[j].y);
    18.             }
    19.     ReleaseDC(hwnd, hdc);
    20. }
    21. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
    22. {
    23.     static  std::vector<POINT>  vtPoints;   // Lưu các điểm
    24.     static  BOOL                bLines;     // Quản lý vẽ: 0-chỉ vẽ điểm. 1-vẽ đầy đủ
    25.     PAINTSTRUCT                 ps;
    26.  
    27.     switch (message)
    28.     {
    29.     case WM_RBUTTONDOWN:
    30.         vtPoints.clear();
    31.         bLines = 0;
    32.         InvalidateRect(hwnd, NULL, TRUE);
    33.         return 0;
    34.     case WM_LBUTTONDOWN:
    35.         // Nếu người dùng đã dblclk trước đó rồi thì mỗi khi click thêm 1 điểm mới, sẽ vẽ lại cả các đường từ điểm này
    36.         // nên nếu muốn người dùng phải RightClick xóa rồi mới thực hiện lại từ đầu thì mở 2 dòng ngay dưới
    37.         //if (bLines)
    38.             //return 0;
    39.         vtPoints.push_back({ LOWORD(lparam), HIWORD(lparam) });
    40.         Draw(hwnd, vtPoints, bLines);
    41.         return 0;
    42.     case WM_LBUTTONDBLCLK:
    43.         bLines = 1;
    44.         Draw(hwnd, vtPoints, bLines);
    45.         return 0;
    46.     case WM_PAINT:
    47.         BeginPaint(hwnd, &ps);
    48.         EndPaint(hwnd, &ps);
    49.         Draw(hwnd, vtPoints, bLines);
    50.         return 0;
    51.     case WM_DESTROY:
    52.         vtPoints.clear();
    53.         PostQuitMessage(0);
    54.         return 0;
    55.     }
    56.     return DefWindowProc(hwnd, message, wparam, lparam);
    57. }
    58. int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow)
    59. {
    60.     WNDCLASS    w;
    61.     w.cbClsExtra = 0;
    62.     w.cbWndExtra = 0;
    63.     w.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    64.     w.hCursor = LoadCursor(NULL, IDC_ARROW);
    65.     w.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    66.     w.hInstance = hInst;
    67.     w.lpfnWndProc = WndProc;
    68.     w.lpszClassName = "Points";
    69.     w.lpszMenuName = NULL;
    70.     w.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
    71.     if (!RegisterClass(&w))
    72.         return 0;
    73.     HWND    hwnd = CreateWindow(w.lpszClassName, w.lpszClassName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, NULL);
    74.     ShowWindow(hwnd, nShow);
    75.     UpdateWindow(hwnd);
    76.     MSG     msg;
    77.     while (GetMessage(&msg, NULL, 0, 0))
    78.     {
    79.         TranslateMessage(&msg);
    80.         DispatchMessage(&msg);
    81.     }
    82.     return msg.wParam;
    83. }
    Yêu mã hơn yêu em !!!

  3. #3
    Ngày gia nhập
    05 2012
    Bài viết
    12

    Cảm ơn bác !
    Bác siêu thật í...
    .
    Em thì làm được rồi, nhưng mà không hiểu sao hàm WM_LBUTTONDBLCLK của e k chạy được.
    Nếu đặt là cái khác... kiểu như WM_MBUTTONDOWN thì click chuột giữa ok... nhưng để là double click thì k được. Hay do e k biết ấn double click như thế nào mới chuẩn vậy ạ.
    -
    Bác gặp trường hợp này bao giờ chưa ? Chỉ giúp e với ạ.

  4. #4
    Ngày gia nhập
    02 2014
    Nơi ở
    TP.HCM
    Bài viết
    706

    Thủa trước tôi cũng như bạn vậy, cứ nghĩ rằng mình viết sai đâu đó, thực ra chẳng có gì khó hiểu. Một cửa sổ muốn nhận WM_LBUTTONDBLCLK thì khi đăng ký lớp - trường style phải có cờ CS_DBLCLKS được bật (dòng 70 ở mã trên).
    Yêu mã hơn yêu em !!!

  5. #5
    Ngày gia nhập
    05 2012
    Bài viết
    12

    Trích dẫn Nguyên bản được gửi bởi MHoang Xem bài viết
    Thủa trước tôi cũng như bạn vậy, cứ nghĩ rằng mình viết sai đâu đó, thực ra chẳng có gì khó hiểu. Một cửa sổ muốn nhận WM_LBUTTONDBLCLK thì khi đăng ký lớp - trường style phải có cờ CS_DBLCLKS được bật (dòng 70 ở mã trên).
    Chuẩn luôn rồi bạn. Tuyệt vời luôn. Mấy cái nhỏ nhỏ k để ý lại khiến mình nghĩ mãi k biết tại đâu.

    Cảm ơn bạn nhiều

    - - - Nội dung đã được cập nhật ngày 19-06-2017 lúc 10:44 PM - - -

    À ! Bạn cho mình hỏi. mình có bài yêu cầu.
    Tạo cửa sổ có menu Chức năng > Đăng ký học.
    Click vào hình ảnh để lấy hình ảnh lớn

Tên:		234.png
Lần xem:	0
Size:		26.4 KB
ID:		55179
    Mình tạo dialogbox thì đơn giản rồi ( vào Resource tạo, rồi kéo thả cho ra như hình là được ) Nhưng làm sao có thể đổ dữ liệu vào listview đó được rồi xử lý các button để đẩy từ listview 1 sang listview 2.
    Mình đã thử dùng WM_Create: nhưng k thấy add được dữ liệu khi load dialogbox lên í.
    --- Bạn giúp mình với nhé !

  6. #6
    Ngày gia nhập
    02 2014
    Nơi ở
    TP.HCM
    Bài viết
    706

    Mặc định [Win32 API] Nhờ hướng dẫn Click chuột để vẽ điểm ảnh và nối các điểm

    Với DialogBox hoặc CreateDialog, Windows không bao giờ gởi WM_CREATE tới thủ tục cửa sổ, cái bạn cần là xử lý thông điệp WM_INITDIALOG. Việc đưa dữ liệu từ listview này sang listview khác thì chỉ đơn thuần là tính toán, bạn tham khảo tập lệnh, hàm, macro từ MSDN là có đầy đủ đồ chơi.

    Như hình trên thì chắc là bạn đang dùng VB và các khung trắng là listbox chứ không phải listview, tuy nhiên cũng đưa một đoạn theo listview cho bạn dễ hình dung
    Ví dụ : button thứ 2 ở hình trên là di chuyển tất cả chỉ mục của lv1 sang lv2 có thể như :
    C++ Code:
    1. #include<Windows.h>
    2. #include<time.h>
    3. #include<CommCtrl.h>
    4. #include"resource.h"
    5. #pragma comment(lib, "comctl32.lib")
    6.  
    7. void InitColumn(HWND hList)
    8. {
    9.     LVCOLUMN    lvc;
    10.     lvc.mask = LVCF_WIDTH | LVCF_TEXT;
    11.     lvc.cx = 100;
    12.     lvc.pszText = "XYZ";
    13.     ListView_InsertColumn(hList, 0, &lvc);
    14. }
    15. void InitItems(HWND hList)
    16. {
    17.     // Tạo dữ liệu ngẫu nhiên để kiểm tra
    18.    
    19.     int     cItems = rand() % 16 + 5;           // Số dòng trong khoảng [5,20]
    20.     char    szBuffer[21];
    21.     int     nLen;
    22.     LVITEM  lvi;
    23.  
    24.     lvi.mask = LVIF_TEXT;
    25.     lvi.iSubItem = 0;
    26.  
    27.     for (int i = 0; i < cItems; i++)
    28.     {
    29.         nLen = rand() % 16 + 5;                 // Số ký tự cho iTems này [5,20]
    30.         ZeroMemory(szBuffer, 21);
    31.         for (int j = 0; j < nLen; j++)
    32.             szBuffer[j] = rand() % 95 + 32;     // Các ký tự in thông thường [32,126]
    33.         lvi.iItem = i;
    34.         lvi.pszText = szBuffer;
    35.         ListView_InsertItem(hList, &lvi);
    36.     }
    37. }
    38. void MoveAll(HWND hList1, HWND hList2)
    39. {
    40.     int     cItems1 = ListView_GetItemCount(hList1);
    41.     int     cItems2 = ListView_GetItemCount(hList2);
    42.     char    szBuffer[MAX_PATH];
    43.     LVITEM  lvi;
    44.  
    45.     lvi.mask = LVIF_TEXT;
    46.     lvi.iSubItem = 0;
    47.     for (int i = 0; i < cItems1; i++)
    48.     {
    49.         ListView_GetItemText(hList1, i, 0, szBuffer, MAX_PATH);     // Lấy từ 1
    50.         lvi.iItem = cItems2++;
    51.         lvi.pszText = szBuffer;
    52.         ListView_InsertItem(hList2, &lvi);                          // Ghi vào 2
    53.     }
    54.     ListView_DeleteAllItems(hList1);    // Xong : xóa 1
    55. }
    56. BOOL CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wparam, LPARAM lparam)
    57. {
    58.     static  HWND    hList1, hList2;     // Các cửa sổ Listview
    59.  
    60.     switch (message)
    61.     {
    62.     case WM_INITDIALOG:
    63.         // Trong thiết kế các listview đã được chuyển chế độ xem là Report
    64.         hList1 = GetDlgItem(hDlg, IDC_LIST1);   // IDC_LIST1 : ID của listview bên trái khi thiết kế
    65.         hList2 = GetDlgItem(hDlg, IDC_LIST2);   // IDC_LIST2 : ID của listview bên phải khi thiết kế
    66.         InitColumn(hList1);
    67.         InitColumn(hList2);
    68.         srand((unsigned int)time(NULL));
    69.         InitItems(hList1);
    70.         InitItems(hList2);
    71.         return TRUE;
    72.     case WM_COMMAND:
    73.         switch (LOWORD(wparam))
    74.         {
    75.         case IDC_BUTTON2:       // Ví dụ với Button di chuyển tất cả các chỉ mục từ lv1 sang lv2
    76.             MoveAll(hList1, hList2);
    77.             return TRUE;
    78.         // Các lệnh khác ....
    79.         //case IDC_FINISH:  // button kết thúc
    80.         case IDOK:          // nhấn phím Enter
    81.         case IDCANCEL:      // nhấn phím Esc
    82.             SendMessage(hDlg, WM_CLOSE, 0, 0);
    83.             return TRUE;
    84.         }
    85.         break;
    86.     case WM_CLOSE:
    87.         EndDialog(hDlg, 0);
    88.         return TRUE;
    89.     }
    90.     return FALSE;
    91. }
    Yêu mã hơn yêu em !!!

  7. #7
    Ngày gia nhập
    05 2012
    Bài viết
    12

    Mình copy đoạn mã của bạn mà bị lỗi Unicode bạn à ?
    Error 2 error C2440: '=' : cannot convert from 'char [21]' to 'LPWSTR'

    --Mình thử để Charactor set thành Not set thì chạy được... nhưng không hiển thị tiếng việt có dấu nữa bạn à.
    _
    Mình dùng C++ win32 í.

    Cái list mình nói ở trên là listbox í bạn, mình nhầm tên. hì.
    - Làm theo của bạn thì mình chỉ có List Control trong Toolbox và làm được thôi ấy.

  8. #8
    Ngày gia nhập
    02 2014
    Nơi ở
    TP.HCM
    Bài viết
    706

    Bạn viết theo mẫu dự án Win32 nên mặc định nó biên dịch theo phiên bản Unicode. Mình thường xuyên xây dựng từ dự án trống và nó mặc định không Unicode.

    Khắc phục :
    _ Tất cả các chuỗi thêm tiền ngữ : vi dụ : "abcdef" -> L"abcdef".
    _ Chuyển các khai báo từ ký tự đơn sang ký tự rộng: char, CHAR -> WCHAR; char*, PCHAR -> PWCHAR.

    Nói chung lập trình API nên xây dựng từ dự án trống. Mã nguồn có thể biên dịch theo 2 thể loại Unicode và Non-Unicode.
    Với biên dịch Non-Unicode, ta dùng CHAR, PCHAR cho ký tự và con trỏ ký tự. Các chuỗi chỉ cần để trong cặp dấu nháy : "abcdef"
    Với biên dịch Unicode, ta dùng WCHAR, PWCHAR cho ký tự và con trỏ ký tự. Các chuỗi cần thêm tiền ngữ L : L"abcdef"
    Với mã nguồn chung, ta chưa biết nên biên dịch theo hướng nào, ta dùng TCHAR, PTCHAR. Các chuỗi để trong Macro TEXT : TEXT("abcdef")

    Phần chương trình bạn, dùng listbox thì càng dễ hơn nữa, không cần include thêm CommCtrl.h vào và mã cũng đơn giản hơn - chẳng cần khởi tạo cột lẫn dòng, chỉ cộng - xóa đơn giản.
    Yêu mã hơn yêu em !!!

  9. #9
    Ngày gia nhập
    05 2012
    Bài viết
    12

    Cho mình hỏi nốt 1 cái nữa thôi nhé !
    Sao mình lấy được giá trị đang selected để mình chỉ đưa giá trị đó sang vậy ?

    Click vào hình ảnh để lấy hình ảnh lớn

Tên:		Capture.JPG
Lần xem:	2
Size:		47.1 KB
ID:		55264

    Mình sử dụng như hình, bỏ vòng for của bạn thôi... nhưng chỉ get được giá trị dòng thứ 2 thôi ạ ?

  10. #10
    Ngày gia nhập
    02 2014
    Nơi ở
    TP.HCM
    Bài viết
    706

    Với Listview thì nó cho phép chọn nhiều Items nên phải dò tìm tất cả các Items đã chọn, bạn có thể làm như sau :
    C++ Code:
    1. void MoveSelectedItems(HWND hFrom, HWND hTo)
    2. {
    3.     int     cItems1 = ListView_GetItemCount(hFrom);
    4.     int     cItems2 = ListView_GetItemCount(hTo);
    5.     WCHAR   szBuffer[MAX_PATH];
    6.     LVITEM  lvi;
    7.     lvi.mask = LVIF_TEXT;
    8.     lvi.iSubItem = 0;
    9.     for (int i = 0; i < cItems1; i++)
    10.     {
    11.         if ((ListView_GetItemState(hFrom, i, LVIS_SELECTED)) == LVIS_SELECTED)  // Item này được chọn ?
    12.         {
    13.             ListView_GetItemText(hFrom, i, 0, szBuffer, MAX_PATH);  // Lấy từ 1
    14.             lvi.iItem = cItems2++;
    15.             lvi.pszText = szBuffer;
    16.             ListView_InsertItem(hTo, &lvi);                         // Ghi vào 2
    17.             ListView_DeleteItem(hFrom, i);                          // Xong : xóa 1
    18.             i--;            // Xét trở lại chỉ mục này vì phía sau đã dồn lên 1
    19.             cItems1--;      // Số items đã giảm 1
    20.         }
    21.     }
    22. }

    Chương trình bên dưới, khi gọi hộp thoại từ trình đơn Demo, hộp thoại sẽ khởi tạo các dòng. Khi người dùng đã di chuyển qua lại và nhấn kết thúc, hộp thoại trả về danh mục các môn học mà người dùng đăng ký. Cửa sổ chính sẽ in danh sách chọn ra vùng Client. Được viết từ dự án C++\Win32 cho Unicode trên VS2015.
    Attached Files Attached Files
    Yêu mã hơn yêu em !!!

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn