Почему ListView не выводится на экран ?
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.9] |
|
|
Правила раздела C/C++: Системное программирование и WinAPI
FAQ Сайта (C++)
FAQ Форума
Наши Исходники
Поиск по Разделу
MSDN Library Online (Windows Driver Kit)
Google
Почему ListView не выводится на экран ?
|
Сообщ.
#1
,
|
|
|
|
[attach=#0][/attach][attach=#0][/attach]Добрый вечер!
Решил соорудить простой пример ListView на WinApi, но, к сожалению, я так и не смог заставить его заработать. Видно, что он что-то пытается вывести (см. серую полоску) вверху окна, но это не совсем то, что надо. Код прилагается. InitInstance создает главное окно, вызывает: - CreateListView - для создания окна ListView, - InsertListViewItems - для создания элементов ListView. Обработчик WM_MOTIFY - в конце текста, он вызывается. Не поможете разобраться - что не так, почему ListView нормально не рисуется ? Вот код (это вся программа). ![]() ![]() #pragma comment( lib, "comctl32" ) #include "framework.h" #include "commctrl.h" #include <windowsx.h> // HANDLE_MSG #include "ProcList.h" #include <assert.h> #define MAX_LOADSTRING 100 // Глобальные переменные: HINSTANCE hInst; // текущий экземпляр WCHAR szTitle[MAX_LOADSTRING]; // Текст строки заголовка WCHAR szWindowClass[MAX_LOADSTRING]; // имя класса главного окна // Отправить объявления функций, включенных в этот модуль кода: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); // -------------------------- HWND CreateListView(HINSTANCE hInstance, HWND hwndParent); BOOL InsertListViewItems(HWND hWndListView, int cItems); void HandleWM_NOTIFY(LPARAM lParam); int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); INITCOMMONCONTROLSEX InitCtrls; InitCtrls.dwICC = ICC_LISTVIEW_CLASSES; InitCtrls.dwSize = sizeof(INITCOMMONCONTROLSEX); BOOL bRet = InitCommonControlsEx(&InitCtrls); assert(bRet == TRUE); //InitCommonControls(); // Инициализация глобальных строк LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadStringW(hInstance, IDC_PROCLIST, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // Выполнить инициализацию приложения: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PROCLIST)); MSG msg; // Цикл основного сообщения: while (GetMessage(&msg, nullptr, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } // // ФУНКЦИЯ: MyRegisterClass() // // ЦЕЛЬ: Регистрирует класс окна. // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEXW wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PROCLIST)); wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_PROCLIST); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassExW(&wcex); } // // ФУНКЦИЯ: InitInstance(HINSTANCE, int) // // ЦЕЛЬ: Сохраняет маркер экземпляра и создает главное окно // // КОММЕНТАРИИ: // // В этой функции маркер экземпляра сохраняется в глобальной переменной, а также // создается и выводится главное окно программы. // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; // Сохранить маркер экземпляра в глобальной переменной HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr); if (!hWnd) { return FALSE; } HWND hListView = CreateListView(hInstance, hWnd); assert(hListView != 0); if (!hListView) { BOOL ok = InsertListViewItems(hListView, 5); } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); if (!hListView) { ShowWindow(hListView, SW_SHOW); UpdateWindow(hListView); } return TRUE; } // // ФУНКЦИЯ: WndProc(HWND, UINT, WPARAM, LPARAM) // // ЦЕЛЬ: Обрабатывает сообщения в главном окне. // // WM_COMMAND - обработать меню приложения // WM_PAINT - Отрисовка главного окна // WM_DESTROY - отправить сообщение о выходе и вернуться // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_COMMAND: { int wmId = LOWORD(wParam); // Разобрать выбор в меню: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } } break; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); // TODO: Добавьте сюда любой код прорисовки, использующий HDC... EndPaint(hWnd, &ps); } break; case WM_DESTROY: PostQuitMessage(0); break; // ----------------------- case WM_NOTIFY: HandleWM_NOTIFY(lParam); break; // ----------------------- default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // Обработчик сообщений для окна "О программе". INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; } // CreateListView: Creates a list-view control in report view. // Returns the handle to the new control // TO DO: The calling procedure should determine whether the handle is NULL, in case // of an error in creation. // // HINST hInst: The global handle to the application instance. // HWND hWndParent: The handle to the control's parent window. // HWND CreateListView(HINSTANCE hInstance, HWND hwndParent) { INITCOMMONCONTROLSEX icex; // Structure for control initialization. icex.dwICC = ICC_LISTVIEW_CLASSES; InitCommonControlsEx(&icex); RECT rcClient; // The parent window's client area. GetClientRect(hwndParent, &rcClient); // Create the list-view window in report view with label editing enabled. HMENU hMenu = NULL; // (HMENU)IDM_CODE_SAMPLES HWND hWndListView = CreateWindow(WC_LISTVIEW, L"", WS_CHILD | LVS_REPORT | LVS_EDITLABELS | WS_VISIBLE, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, hwndParent, hMenu, hInstance, NULL); return (hWndListView); } // InsertListViewItems: Inserts items into a list view. // hWndListView: Handle to the list-view control. // cItems: Number of items to insert. // Returns TRUE if successful, and FALSE otherwise. BOOL InsertListViewItems(HWND hWndListView, int cItems) { LVITEM lvI = { 0 }; // Initialize LVITEM members that are common to all items. lvI.pszText = LPSTR_TEXTCALLBACK; // Sends an LVN_GETDISPINFO message. lvI.mask = LVIF_TEXT | /*LVIF_IMAGE | */ LVIF_STATE; lvI.stateMask = 0; lvI.iSubItem = 0; lvI.state = 0; // Initialize LVITEM members that are different for each item. for (int index = 0; index < cItems; index++) { lvI.iItem = index; lvI.iImage = index; // Insert items into the list. int ErrCode = ListView_InsertItem(hWndListView, &lvI); assert(ErrCode == 0); //return FALSE; int NewColWidth = LVSCW_AUTOSIZE; BOOL ok_set = ListView_SetColumnWidth(hWndListView, index, NewColWidth); assert(ok_set == TRUE); } return TRUE; } // HandleWM_NOTIFY - Handles the LVN_GETDISPINFO notification code that is // sent in a WM_NOTIFY to the list view parent window. The function // provides display strings for list view items and subitems. // // lParam - The LPARAM parameter passed with the WM_NOTIFY message. // rgPetInfo - A global array of structures, defined as follows: struct PETINFO { TCHAR szKind[10]; TCHAR szBreed[50]; TCHAR szPrice[20]; }; PETINFO rgPetInfo[ ] = { {TEXT("Dog"), TEXT("Poodle"), TEXT("$300.00")}, {TEXT("Cat"), TEXT("Siamese"), TEXT("$100.00")}, {TEXT("Fish"), TEXT("Angel Fish"), TEXT("$10.00")}, {TEXT("Bird"), TEXT("Parakeet"), TEXT("$5.00")}, {TEXT("Toad"), TEXT("Woodhouse"), TEXT("$0.25")}, }; void HandleWM_NOTIFY(LPARAM lParam) { NMLVDISPINFO* plvdi; switch (((LPNMHDR)lParam)->code) { case LVN_GETDISPINFO: plvdi = (NMLVDISPINFO*)lParam; switch (plvdi->item.iSubItem) { case 0: plvdi->item.pszText = rgPetInfo[plvdi->item.iItem].szKind; break; case 1: plvdi->item.pszText = rgPetInfo[plvdi->item.iItem].szBreed; break; case 2: plvdi->item.pszText = rgPetInfo[plvdi->item.iItem].szPrice; break; default: break; } break; } // NOTE: In addition to setting pszText to point to the item text, you could // copy the item text into pszText using StringCchCopy. For example: // // StringCchCopy(plvdi->item.pszText, // plvdi->item.cchTextMax, // rgPetInfo[plvdi->item.iItem].szKind); return; } |
|
Сообщ.
#2
,
|
|
|
|
Цитата Lun2 @ Не поможете разобраться - что не так, почему ListView нормально не рисуется ? А вот это - зачем ? ![]() ![]() if (!hListView) { (в функции InitInstance) |
|
Сообщ.
#3
,
|
|
|
|
А кто будет добавлять столбцы перед добавлением строк?
![]() ![]() LVCOLUMN lvColumn = { 0 }; lvColumn.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; lvColumn.pszText = const_cast<LPWSTR>(L"Column 1"); lvColumn.cx = 200; // Width of the column ListView_InsertColumn(hWndListView, 0, &lvColumn); LVITEM lvI = { 0 }; // Initialize LVITEM members that are common to all items. lvI.pszText = LPSTR_TEXTCALLBACK; // Sends an LVN_GETDISPINFO message. lvI.mask = LVIF_TEXT | /*LVIF_IMAGE | */ LVIF_STATE; lvI.stateMask = 0; lvI.iSubItem = 0; lvI.state = 0; А это зачем? Почему не вернуть 0 в случае завершения программы? ![]() ![]() return (int) msg.wParam; Инициализацию InitCommonControlsEx нужно делать всего один раз. Причем во второй инициализации вы не задали размер структуры ![]() ![]() InitCtrls.dwSize = sizeof(INITCOMMONCONTROLSEX); Добавляем только если не удалось создать окно????? ![]() ![]() if (!hListView) { BOOL ok = InsertListViewItems(hListView, 5); } P.S. На кой вам писать оконный интерфейс на чистом WinAPI? Это же мазохизм чистой воды.Ну посмотрите хотя бы в сторону MFC. Про остальные фреймворки я уж не говорю. |
|
Сообщ.
#4
,
|
|
|
|
Цитата sharky72 @ А кто будет добавлять столбцы перед добавлением строк? sharky72, спасибо! Вы правы - надо было добавить столбцы! Цитата sharky72 @ P.S. На кой вам писать оконный интерфейс на чистом WinAPI? Это же мазохизм чистой воды.Ну посмотрите хотя бы в сторону MFC. Про остальные фреймворки я уж не говорю. Предыдущие мои разборки (с другими диалогами) были как раз с MFC. Не сказать, чтоб слишком просто и быстро ![]() В этой задаче мне нужен только ListView, а не богатый интерфейс в целом (ну может пара кнопок еще). Я посчитал, что изучение MFC и одного Listview winapi не больно-то и отличаются по времени. |
|
Сообщ.
#5
,
|
|
|
|
Цитата Lun2 @ В этой задаче мне нужен только ListView, а не богатый интерфейс в целом (ну может пара кнопок еще). Я посчитал, что изучение MFC и одного Listview winapi не больно-то и отличаются по времени. Ну и зря. Количество кода которого надо набить руками в WinAPI и MFC различается порядками. Плюс стоит вам чуть выйти за пределы "академических" экзерцисов, в сторону хоть какого то вменяемого UI который бы работал на современном железе и поддерживал современные системы и те же HiDPI мониторы - мое вам сочувствие. Забудьте. Так же как писать под винду на асме. Можно, но пахнет редкими извращениями. |