Редактируемый List Control
Метод: субклассинг.
Редактируемость: дабл клик на суб-айтеме вызывает поверх него окно Эдит Бокс, Энтер нажатый в Эдите изменяет текст в лист контроле.
cEdit_Item->Create(WS_CHILD | ES_MULTILINE | ES_AUTOHSCROLL,CRect(0,0,0,0),this,WM_USER+254);
С Эдитом получилось.
Вопрос №1: как оловить изменение ширины столбцов в Лист Контроле?(а то сразу видно что Эдит бокс просто идет поверх Лист-а)
Вопрос №2: с Комбо Боксом хуже во-первых не работает
Создаю так:
cCombo_Item->Create( NULL, NULL, WS_VISIBLE | WS_TABSTOP | WS_CHILD , CRect(0,0,0,0), this, WM_USER+255, 0);
во-вторых Комбо Бокс по высоте слишком большой--> хотелось бы хоть увеличить высоту строк в Лист Контроле
Вопрос №3:
по нажатию на некоторые суб-айтемы вызываю диалог открытия/сохранения файла:
{
TCHAR szFile[2048]={0};
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = AfxGetApp()->m_pMainWnd->m_hWnd;
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = 0;
ofn.lpstrTitle = TEXT("Отктыть Файл!!!!!!!");
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = TEXT("All\0*.*\0");
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
*bt=GetOpenFileName(&ofn);
return szFile;
}
-работает, НО после закрытия программы Винда (Виста) пишет шо типа какой то БАГ:
This may be due to a corruption of the heap, which indicates a bug in Dialog.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while Dialog.exe has focus.
The output window may have more diagnostic information.
Помогите!!!
Вопрос №1: как оловить изменение ширины столбцов в Лист Контроле?(а то сразу видно что Эдит бокс просто идет поверх Лист-а)
CListCrtl отправляет родителю следующией Notify HDN_BEGINTRACK, HDN_TRACK и HDN_ENDTRACK, когда начинается, осуществляется и заканчивается изменение размеров. Кроме того, заголовок - это тоже окно и оно является дочерним для самого ListCtrl, так что можете посмотреть какие сообщения приходят ListCtrl от заголовка в процессе перетаскивания.
во-вторых Комбо Бокс по высоте слишком большой--> хотелось бы хоть увеличить высоту строк в Лист Контроле
ListCtrl сам определяет высоту элементов в зависимости от заданного ему шрифта. Чтобы это изменить надо либо создавать ListCtrl как OwnerDraw и обрабатывать сообщения WM_DRAWITEM, WM_MEASUREITEM, но в этом случае вся прорисовка "ложится" на вас. Либо изменить высоту самого ComboBox'а. Как это делается обсуждалось не так давно где-то в этом разделе. Поищите.
Вопрос №3:
по нажатию на некоторые суб-айтемы вызываю диалог открытия/сохранения файла:
{
TCHAR szFile[2048]={0};
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = AfxGetApp()->m_pMainWnd->m_hWnd;
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = 0;
ofn.lpstrTitle = TEXT("Отктыть Файл!!!!!!!");
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = TEXT("All\0*.*\0");
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
*bt=GetOpenFileName(&ofn);
return szFile;
}
-работает, НО после закрытия программы Винда (Виста) пишет шо типа какой то БАГ:
This may be due to a corruption of the heap, which indicates a bug in Dialog.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while Dialog.exe has focus.
The output window may have more diagnostic information.
Помогите!!!
Эта же функция откомпилированная в MSVS2005 и запущенная в XP работает без проблем. Но я сомневаюсь, что проблема в Vist'е. Раз возникает Heap corruption, значит скорее всего где-то неправильно работаете с указателем. Причем не факт, что именно в этой функции.
CListCrtl отправляет родителю следующией Notify HDN_BEGINTRACK, HDN_TRACK и HDN_ENDTRACK, когда начинается, осуществляется и заканчивается изменение размеров. Кроме того, заголовок - это тоже окно и оно является дочерним для самого ListCtrl, так что можете посмотреть какие сообщения приходят ListCtrl от заголовка в процессе перетаскивания.
Сообщение ввиде
не приходит, а ON_NOTIFY я не знаю ID-заголовка.
не приходит, а ON_NOTIFY я не знаю ID-заголовка.
Как выснилось, эти оповещения приходят сначала самому ListCtrl. Так что создав свой дочерний от ListCtrl класс у меня получилось перехватить их примерно следующим способом:
#pragma once
#include "afxcmn.h"
class CListChild: public CListCtrl
{
public:
CListChild(void);
~CListChild(void);
public:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnHdnEndtrack(NMHDR *pNMHDR, LRESULT *pResult);
};
....................................................................................................
//ListChild.cpp
#include "StdAfx.h"
#include "ListChild.h"
CListChild::CListChild(void)
{
}
CListChild::~CListChild(void)
{
}
BEGIN_MESSAGE_MAP(CListChild, CListCtrl)
ON_NOTIFY(HDN_ENDTRACKA, 0, &CListChild::OnHdnEndtrack)
ON_NOTIFY(HDN_ENDTRACKW, 0, &CListChild::OnHdnEndtrack)
END_MESSAGE_MAP()
void CListChild::OnHdnEndtrack(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);
// TODO: Add your control notification handler code here
::MessageBox(NULL, "OK", "OK", MB_OK);
*pResult = 0;
}
НО что это такое:
HDN_BEGINTRACK W
И почему работает именно в паре?!
Впервые вижу, MSDN такое тоже не знает?!
то надо ли, а если надо то где (в деструкторе?), ДЕЛАТЬ
{
if(bEdit_Box)
delete(cEdit_Item);
}
НО что это такое:
HDN_BEGINTRACK W
И почему работает именно в паре?!
Впервые вижу, MSDN такое тоже не знает?!
Разница в том, определена или нет константа UNICODE. В зависимости от этого отправляются разные сообщения.
то надо ли, а если надо то где (в деструкторе?), ДЕЛАТЬ
{
if(bEdit_Box)
delete(cEdit_Item);
}
Да. Родитель уничтожит окно, но не уничтожит объект MyList.
А как именно ловите сообщение о том что нажата клавиша Enter в Edit'е?
Я уже битый час с этим мучаюсь.
2: Удалять Эдит надо только после ОТПАДА необходимости в List-Ctrl (родитель для Эдита), т.к. создается он только один раз если тот кто инициализирует List-Ctrl возжелает что-бы какие либо столбцы редактировались в такой способ. Далее просто Эдит то прячется (SW_HIDE), либо появляется (SW_SHOW), вот и все так што проблемы лишней памяти могут быть только если неудаляя List-Ctrl пытаться его еще раз создать.
P.S. Код стал стабильным толко когда я сделал так:
{
//тут нет удаления Edit.
}
Спасибо за внимание!!
А да, а если я хочу сделать колонку состояния прогресса (50%, например как в uTorrent), то единственный выход- OWNER_DRAW ? (может есть возвожность что бы он сам отрисовал ::OnPaint(), а я просто дорисовал??)
CyBOSSeR:
А как именно ловите сообщение о том что нажата клавиша Enter в Edit'е?
Я уже битый час с этим мучаюсь.
2: Делаешь суб-класс на CEdit, там обрабатываешь сообщение WM_KEYDOWN, где ловишь VK_RETURN, далее както надо родительскому окну сообщить об этом: лично я отправляю свое сообщение.
CyBOSSeR:
Да, нужно:
И в каждый раз когда отпадает необходимость в данном Edit'е (т.е. после нажатия клавиши Enter в нем), также необходимо очистить память, выделенную под него. А то получается, что в каждый раз когда пользователь дважды щелкает по элементу у Вас память выделяется и ни разу не очищается.
2: Удалять Эдит надо только после ОТПАДА необходимости в List-Ctrl (родитель для Эдита), т.к. создается он только один раз если тот кто инициализирует List-Ctrl возжелает что-бы какие либо столбцы редактировались в такой способ. Далее просто Эдит то прячется (SW_HIDE), либо появляется (SW_SHOW), вот и все так што проблемы лишней памяти могут быть только если неудаляя List-Ctrl пытаться его еще раз создать.
P.S. Код стал стабильным толко когда я сделал так:
{
//тут нет удаления Edit.
}
Спасибо за внимание!!
А да, а если я хочу сделать колонку состояния прогресса (50%, например как в uTorrent), то единственный выход- OWNER_DRAW ? (может есть возвожность что бы он сам отрисовал ::OnPaint(), а я просто дорисовал??)
А да, а если я хочу сделать колонку состояния прогресса (50%, например как в uTorrent), то единственный выход- OWNER_DRAW ? (может есть возвожность что бы он сам отрисовал ::OnPaint(), а я просто дорисовал??)
Почему же? Можно. Допустим так
dc->LineTo(100, 100);
но при этом придется еще и обрабатывать OnPaint, чтобы знать, когда область с нарисованным вами стала недйствительным. Вообщем на мой взгляд OwnerDraw подходит для таких вещей лучше.
Можешь, пожалуйста выложить код сабкласса CEDit'а, а то честно говоря хочется на примере посмотреть что за зверь такой сабклассинг, ну или хотя бы статью хорошую про сабклассинг в MFC.
И еще в своей программе для определения того, что пользователь нажал клавишу Enter в CEdit'e я немного переделал функцию PreTranslateMessage, а именно:
{
if (TranslateAccelerator(*this,m_hAccel,pMsg))
return TRUE;
if(pMsg->message==WM_KEYDOWN&&pMsg->wParam==VK_RETURN&&GetFocus()==m_pEdit) // m_pEdit - указатель на Едитбокс
EndEdit(); // функция обработки завершения ввода
return CDialog::PreTranslateMessage(pMsg);
}
{
тут можно добавить свои переменные и процедуры (либо переопределить существующие)
};
На счет PreTranslate- тут не нужно достаточно
ON_WM_KEYDOWN()
END_MESSAGE_MAP()
- говорим что нам надо обработать вот это сообщение
А затем собственно обрабатываем:
{
if (i==VK_RETURN)
hWnd_parent->SendMessage(WM_COMMAND, Message_Enter, NULL);
}
//hWnd_parent- указатель на CWnd- ему я сам (ручками) присваиваю значение, например:
cEdit_Item->Create(WS_CHILD | ES_MULTILINE | ES_AUTOHSCROLL,CRect(0,0,0,0),this,WM_USER+2254);
cEdit_Item->Message_Enter=ID_EDIT_ENTER;//определенное мной сообщение
cEdit_Item->hWnd_parent=this; //в принципе у CEdit есть поле, содержащее родителя.