Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Win32 API - Текст в ListView и проч.

Ответить
Настройки темы
Win32 API - Текст в ListView и проч.
pva pva вне форума

Аватара для pva

Ветеран


Сообщения: 1180
Благодарности: 279

Профиль | Отправить PM | Цитировать


Изменения
Автор: pva
Дата: 06-11-2007
Описание: нажал tab и пробел - он меня не понял
1. Это только у меня ListView в режиме LVS_REPORT отображает только примерно 100 символов в ячейке, или у всех так? хранит ведь полностью строчку
2. я так и не понял, в каких случаях ReadDirectoryChanges возвращает несколько записей и почему они все одинаковые?
дальше приведён кусочек кода с комментариями. Он опирается на STL и самописную библиотеку напоминающую упрощённую смесь QT и Swing
Код: Выделить весь код
class DirectoryChanges  // класс для ReadDirectoryChangesW
{
    HANDLE          fdirectory;
    OVERLAPPED      foverlapped;
    vector<unsigned char> fbuffer;  // буфер 4К для чтения
    StringEvent*    fevent; // класс с одной пустой виртуальной функцией virtual void put(const wstring&) = 0;
    void restart();
    static void __stdcall _competed(unsigned long, unsigned long, OVERLAPPED*); // FileIoCompletionRoutine
public:
    DirectoryChanges(const wstring& dir);
    ~DirectoryChanges();
    void setEvent(StringEvent* event)   {fevent=event;}
};

// каждый раз, при появлении данных, в ListView добавляется строчка
// вследтсвие вызова fevent->put()

DirectoryChanges::DirectoryChanges(const wstring& dir) :
    fdirectory(CreateFile (    // кусок прямо из хелпа
          dir.c_str(),
          FILE_LIST_DIRECTORY,                // access (read-write) mode
          FILE_SHARE_READ|FILE_SHARE_DELETE,  // share mode
          0,                                  // security descriptor
          OPEN_EXISTING,                      // how to create
          FILE_FLAG_OVERLAPPED|FILE_FLAG_BACKUP_SEMANTICS, // file attributes
          0)),                               // file with attributes to copy
    foverlapped (),
    fbuffer     (4096)
{
    if (fdirectory==(HANDLE)-1)
    {
        ostringstream ss;
        ss << "DirectoryChanges::DirectoryChanges error=" << GetLastError();
        throw runtime_error(ss.str());
    }

    foverlapped.hEvent = reinterpret_cast<HANDLE>(this); // т.к. не используется в FileIoCompletionRoutine, микрософт не против
}

DirectoryChanges::~DirectoryChanges()
{
//    stopListening();
    CloseHandle(fdirectory);
}

void __stdcall DirectoryChanges::_competed(unsigned long code, unsigned long bytes_transfered, OVERLAPPED* ovlp)
{
   // это место выполняется "асинхронным вызовом процедуры", в главном цикле, который обрабатывает сообщения,
   // функцией MsgWaitForMultipleObjectsEx.
    if (code==0)
    {
        try
        {
           // разглядываем что прочитали
            DirectoryChanges* this1 = reinterpret_cast<DirectoryChanges*>(ovlp->hEvent);
            FILE_NOTIFY_INFORMATION* info = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(&this1->fbuffer[0]);

            if (this1->fevent)
            {

                // 1. для начала посмотрим в виде HEX

                wostringstream ss;

                ss.fill('0');
                ss.flags(ios::hex|ios::fixed);

                for (unsigned n=0; n<bytes_transfered; ++n)
                {
                    ss << ' ';
                    ss.width(2);
                    ss << unsigned(this1->fbuffer[n]);
                }

                // выводим полученную строчку в ListView
                this1->fevent->put(ss.str());

               // теперь разбираем результат, как написано в хелпе
                for (;;)  // назовём его "цикл №2"
               {
                    // закидываем строчку в ListView
                    // опытным путём нашёл, что info->FileNameLength измеряется в байтах
                    this1->fevent->put(wstring(info->FileName, info->FileNameLength>>1));

                    if (!info->NextEntryOffset) break; // типа если дошли до конца

                    info = reinterpret_cast<FILE_NOTIFY_INFORMATION*>( // продвигаем указатель
                        reinterpret_cast<char*>(info) + info->NextEntryOffset);
                }

                this1->restart(); // когда закончили с буфером, отправляем читать дальше
            }
        }
// подстраховка, чтобы не порушить стек MsgWaitForMultipleObjectsEx
// потому что у моего компилятора не сильно совместимая система откатов от исключений
        catch (exception& e)
        {
            MessageBoxA(0, e.what(), 0, MB_OK);
        }
        catch (...)
        {
        }
    }
}

void DirectoryChanges::restart()
{
   // читаем всё сподряд
    if (!ReadDirectoryChangesW(fdirectory, &fbuffer[0], fbuffer.size(), true,
                    FILE_NOTIFY_CHANGE_DIR_NAME|
                    FILE_NOTIFY_CHANGE_FILE_NAME|
                    FILE_NOTIFY_CHANGE_ATTRIBUTES|
                    FILE_NOTIFY_CHANGE_SIZE|
                    FILE_NOTIFY_CHANGE_LAST_WRITE|
                    FILE_NOTIFY_CHANGE_LAST_ACCESS|
                    FILE_NOTIFY_CHANGE_CREATION|
                    FILE_NOTIFY_CHANGE_SECURITY, 0, &foverlapped, _competed))
    {
        ostringstream ss;
        ss << "DirectoryChanges::start error=" << GetLastError();
        throw runtime_error(ss.str());
    }
}



class Form1 : public Form
{
    struct event1 : StringEvent {
        Form1* form;
        event1(Form1* f) : form(f) {}
        void put(const wstring&);
    };

    ListView view1;
    DirectoryChanges directory_changes;
    struct event1 event1;

public:
    Form1();
    //void perform(Message&);
};

void Form1::event1::put(const wstring& s)
{
    // void ListView::insertItem(/*позиция*/ control_Id, /*то,что я пожелаю*/ application_Id, /*строчка*/ text, /*ну ещё там кой-чего, инициализируется по умолчанию*/);
    form->view1.insertItem(0, 0, s);

    // чистый API: читаю, что записалось в ListView (может он урезал строчку?)
    vector<wchar_t> buf(4096);
    LV_ITEM lvi = LV_ITEM();
    lvi.mask    = LVIF_TEXT;
    lvi.pszText = &buf[0];
    lvi.cchTextMax = buf.size();

    unsigned size1 = SendMessage(form->view1.handle(), LVM_GETITEMTEXT, 0, long(&lvi));

    // дублирую
    lvi.iSubItem = 2;
    SendMessage(form->view1.handle(), LVM_SETITEMTEXT, 0, long(&lvi));

   // сколько же информации я прочитал? 
   wostringstream ss;
    ss << size1;

// ListView::setItemText(unsigned control_id, unsigned control_col_Id, const wstring& str);
    form->view1.setItemText(0, 1, ss.str());

    // когда это место было раскомментировано, я убедился, что строчка хранится в ListView полностью
    // но тогда начинал "глючить" ReadDirectoryChangesW. Он каждый следующий раз говорил, что
    // изменится мой project1 Debug.exe, причём количество одинаковых записей увеличивалось на 1.
    // то есть первый раз выдалась одна запись
    // второй раз 2 одинаковые ("цикл №2" сработал 2 раза)
    // и так далее, в бесконечном цикле

    //MessageBox(0, &buf[0], 0, MB_OK);   
}

Form1::Form1() :
    view1   (*this, ListView::style_report),
    directory_changes(wstr("d:\\")),
    event1  (this)
{
    directory_changes.setEvent(&event1);
    directory_changes.start();

// ListView::insertColumn(unsigned column_Id, const wstring& str, unsigned width, ...)
    view1.insertColumn(0, wstr("Directory"), 5000);
    view1.insertColumn(1, wstr("Size"), 100);
    view1.insertColumn(2, wstr("Directory 2"), 5000);
    setCenter(&view1); // ну типа растягивается теперь на всю форму
}

Отправлено: 22:54, 06-11-2007

 
pva pva вне форума Автор темы

Аватара для pva

Ветеран


Сообщения: 1180
Благодарности: 279

Профиль | Отправить PM | Цитировать


более продолжительные тесты показали, что ReadDirectoryChangesW может выдавать разные сообщения за один присест. По ходу дела он эти сообщения накапливает у себя. А вот с ListView пока не понял.

Отправлено: 12:36, 07-11-2007 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Win32 API - Текст в ListView и проч.

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
[решено] Как переместить выделенную строку ListView malev AutoIt 3 15-11-2009 12:29
[решено] Сортировка данных ListView по столбцам malev AutoIt 3 16-10-2009 17:53
Интерфейс - Как убрать файл, правка. вид и проч. inkviz Microsoft Windows 2000/XP 0 10-06-2009 00:16
C/C++ - [решено] Вставка иконки в ListView (Builder) ganselo Программирование и базы данных 1 01-06-2009 12:24
ListView редактирование столбцов lesco Программирование и базы данных 2 11-04-2003 22:23




 
Переход