130 / 33 / 4
Регистрация: 18.11.2012
Сообщений: 1,412
1

Петзольд. Работа с LB_DIR и функция OpenFile()

16.09.2023, 08:23. Показов 1465. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте! Хочу спросить вот о чём, в книге Петзольда есть такой пример, он довольно прост, но не работает, так как в примере используется функция OpenFile(), а она требует в качестве параметра строки, строку ascii, но это ерунда, интересует другое. И так вот пример того, как это реализовано у автора:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static BOOL bValidFile;
    static TCHAR szReadBuffer[MAXREAD], szFile[MAXPATH];
    static HWND hwndList, hwndText;
    static OFSTRUCT ofs;
    static RECT rc;
 
    switch (msg)
    {
    case WM_CREATE:
    {
        ofs.cBytes = sizeof(ofs);
        TEXTMETRIC tm;
        HDC hdc = GetDC(hwnd);
        SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
        GetTextMetrics(hdc, &tm);
        ReleaseDC(hwnd, hdc);
 
        rc.left = 20 * tm.tmAveCharWidth;
        rc.top = 3 * tm.tmHeight;
 
        hwndList = CreateWindow(TEXT("listbox"), NULL,
            WS_CHILDWINDOW | WS_VISIBLE |
            LBS_STANDARD /*| LBS_HASSTRINGS*/,
            tm.tmAveCharWidth, tm.tmHeight * 3,
            tm.tmAveCharWidth * 13 +
            GetSystemMetrics(SM_CXVSCROLL),
            tm.tmHeight * 10,
            hwnd, (HMENU)1,
            (HINSTANCE)GetWindowLongPtr(hwnd, GWL_HINSTANCE),
            NULL);
        TCHAR szBuffer[MAXPATH + 1];
        hwndText = CreateWindow(TEXT("static"),
            _tgetcwd(szBuffer, MAXPATH),
            WS_CHILDWINDOW | WS_VISIBLE | SS_LEFT,
            tm.tmAveCharWidth, tm.tmHeight,
            tm.tmAveCharWidth * MAXPATH,
            tm.tmHeight, hwnd,
            (HMENU)2,
            (HINSTANCE)GetWindowLongPtr(hwnd, GWL_HINSTANCE), NULL);
 
        fnOldList = (WNDPROC)SetWindowLongPtr(hwndList,
            GWL_WNDPROC,
            (LPARAM)ListProc);
        SendMessage(hwndList, LB_DIR, 0x37, (LPARAM)TEXT("*.*"));
 
        return 0;
    }
    case WM_SIZE:
    {
        rc.right  = LOWORD(lParam);
        rc.bottom = HIWORD(lParam);
        return 0;
    }
    case WM_SETFOCUS:
    {
        SetFocus(hwndList);
        return 0;
    }
    case WM_COMMAND:
    {
        switch (LOWORD(wParam))
        {
        case 1:
        {
            switch (HIWORD(wParam))
            {
            case LBN_DBLCLK:
            {
                int i;
                if (LB_ERR == (i = SendMessage(hwndList, LB_GETCURSEL, 0, 0)))
                    break;
                TCHAR szBuffer[MAXPATH + 1];
                i = SendMessage(hwndList, LB_GETTEXT, i,
                    (LPARAM)szBuffer);
                szBuffer[i] = '\0';
                /*Здесь, если я правильно понял, по условию функция сама
                  должна определить каталог или файл ей передан в качестве параметра szBuffer и если это каталог, то вернуть ошибку. Но по факту этого не происходит.*/
                
                if (-1 != OpenFile(szBuffer, &ofs, OF_EXIST | OF_READ))
                {
                    bValidFile = TRUE;
                    _tcscpy_s(szFile, MAXPATH, szBuffer);
                    szFile[_tcslen(szFile)-1] = '\0';
                    TCHAR* pPtr = _tgetcwd(szBuffer, MAXPATH);
                    
                    if (szBuffer[_tcslen(szBuffer) - 1] != '\\')
                        _tcscat_s(szBuffer, MAXPATH, TEXT("\\"));
                    _tcscat_s(szBuffer, MAXPATH, szFile);
                    SetWindowText(hwndText, szBuffer);
                }
                else
                {
                    bValidFile = FALSE;
                    szBuffer[_tcslen(szBuffer) - 1] = '\0';
                    
                    _tchdir(szBuffer + 1));
                    _tgetcwd(szBuffer, MAXPATH);
                    
                    SetWindowText(hwndText, szBuffer);
                    SendMessage(hwndList, LB_RESETCONTENT,
                        0, 0L);
                    SendMessage(hwndList, LB_DIR,
                        0x37, (LPARAM)TEXT("*.*"));
                }
                InvalidateRect(hwnd, NULL, TRUE);
                return 0;
            }
            case LB_ERRSPACE:
            //case LBN_MAXTEXT:
            {
                MessageBox(NULL,
                    TEXT("Edit control out of space."),
                    TEXT("ERROR"), MB_OK | MB_ICONSTOP);
                break;
            }
            default:
                break;
            }
        }
        default:
            break;
        }
        return 0;
    }
    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);
        SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
        SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT));
        SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
 
        int iHandle = -1;
        if (bValidFile && (-1 != (iHandle = OpenFile(szFile, &ofs, OF_REOPEN | OF_READ))))
        {
            int i = _lread(iHandle, szReadBuffer, MAXREAD);
                _lclose(iHandle);
            DrawText(hdc, szReadBuffer, i,
                    &rc, DT_WORDBREAK |
                         DT_EXPANDTABS | DT_NOCLIP | DT_NOPREFIX);      
        }
        else
        {
            bValidFile = FALSE;
        }
        EndPaint(hwnd, &ps);
        return 0;
    }
    case WM_DESTROY:
    {
        SetWindowLongPtr(hwndList, GWL_WNDPROC, (LONG_PTR)fnOldList);
        PostQuitMessage(0);
        return 0;
    }
    }
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

Вопрос в том, почему автор задаёт такое условие:
C++
1
if (-1 != OpenFile(szBuffer, &ofs, OF_EXIST | OF_READ))
Видимо, имеется ввиду то, что функция получив в параметре szBuffer значение сама определит каталог это или файл и, если это
не файл, то должно вернуться значение -1 т.е. ошибка.., но это странно... Если же всё в порядке, то функция должна вернуть дескриптор файла, но у меня функция OpenFile(), в случае успеха, возвращает 1, что это за дескриптор такой не ясно.
Так как OpenFile() работает с ascii символами, а я извлекаю символы TCHAR, то я её вызываю так, точнее прежде, чем вызвать функцию я преобразовываю символы, вот так:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
HFILE OpenFileEx(LPCTSTR lpFileName, LPOFSTRUCT lpReOpenBuff, UINT uStyle)
{
    int cchMultiByte = WideCharToMultiByte(CP_ACP, 0, lpFileName,
        -1, NULL,
        0,
        NULL, NULL);
    if (!cchMultiByte)
        return (HFILE)FALSE;
 
    LPSTR lpMultiByteStr = (LPSTR)HeapAlloc(GetProcessHeap(), 0, cchMultiByte * sizeof(TCHAR));
    if (lpMultiByteStr == NULL)
        return (HFILE)FALSE;
 
    int cbByte = WideCharToMultiByte(CP_ACP, 0, lpFileName,
        -1, lpMultiByteStr,
        cchMultiByte,
        NULL, NULL);
 
 
    HFILE hFile = OpenFile(lpMultiByteStr, lpReOpenBuff, uStyle);
    
    HeapFree(GetProcessHeap(), 0, lpMultiByteStr);
    return hFile;
}

Как вообще распознать каталог это или файл в функции CreateFile, возможно ли это? Или всё же нужно дополнительно вызывать функцию GetFileInformationByHandle и уже после её вызова, распознавать, что это каталог или файл?
Ну и по поводу OpenFile() тоже хочется узнать, почему всё же она не работает у меня так как у автора?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
16.09.2023, 08:23
Ответы с готовыми решениями:

функция openfile
почему не работает? FileName db 'C:\test1.exe',0 dd 0 FileOf OFSTRUCT <> push OF_READWRITE...

Как соединить сигнал класса MainWindow openFile c слотом класса MainController openFile?
класс главного окна class MainWindow : public QMainWindow { Q_OBJECT public: ...

nmake и Петзольд
Здравствуйте! В примерах к книге Петзольда проекты собираются с помощью *.mak и *.bat файлов, но...

Петзольд. dll. shared segment
Пример из 19 главы, создается общий сегмент данных и два окна одного класса должны им пользоваться,...

OpenFile нужна помошь!
Собственно у меня есть код procedure TForm2.Button2Click(Sender: TObject); begin if...

14
18465 / 9623 / 2355
Регистрация: 30.01.2014
Сообщений: 16,875
16.09.2023, 12:37 2
Цитата Сообщение от Liss29 Посмотреть сообщение
нужно дополнительно вызывать функцию GetFileInformationByHandle и уже после её вызова, распознавать, что это каталог или файл?
Да.

Цитата Сообщение от Liss29 Посмотреть сообщение
Ну и по поводу OpenFile() тоже хочется узнать, почему всё же она не работает у меня так как у автора?
Потом что у автора не-UNICODE проект.
Если речь идет про эту книгу: "Программирование для Windows 95", то причины прозрачны: в этой системе не было поддержки юникода (да, к ней существует специальное дополнение, которое добавляет ограниченную поддержку, но это вряд ли могло затронуть данную книгу).
0
130 / 33 / 4
Регистрация: 18.11.2012
Сообщений: 1,412
17.09.2023, 00:06  [ТС] 3

Не по теме:

Цитата Сообщение от DrOffset Посмотреть сообщение
Если речь идет про эту книгу: "Программирование для Windows 95"
Да, именно про эту книгу. У него есть другие книги по этой тематике?

Я же преобразовал UNICODE символы к ansi почему и после этого не работает так как надо...



По поводу условия, что оно значит, что должно произойти, если, например, я выбираю в listbox-е, [..], это же, по сути, означает каталог, правильно, значит что, функция должна вернуть -1, но это же ошибка, почему так не могу понять.

C++
1
if (-1 != OpenFile(szBuffer, &ofs, OF_EXIST | OF_READ))
В пень создал такой костыль:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
HANDLE isDirectory(LPCTSTR lpFileName)
{
    HANDLE hFile = CreateFile(lpFileName, GENERIC_READ, FILE_SHARE_READ,
        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
        NULL);
    if (hFile == INVALID_HANDLE_VALUE)
        return hFile;
    //======================
    FILE_BASIC_INFO fbi = { 0 };
    BOOL fOk = GetFileInformationByHandleEx(hFile, FileBasicInfo,
        &fbi, sizeof(fbi));
 
    if (!fOk)
    {
        DWORD er = GetLastError();
        CloseHandle(hFile);
        MessageBox(NULL, TEXT("GetFileInformationByHandleEx is failed"),
            TEXT("Error"), MB_OK);
        return (HANDLE)-1;
    }
    if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
    {
        CloseHandle(hFile);
        return (HANDLE)INVALID_HANDLE_VALUE;
    }
    //--------------------------------------
    return hFile;
}


Но, если я выбираю [..] в каталоге с приложением т.е. место откуда запустил программу, то возвращается результат не каталог, хотя, если перейду в каталог уровнем ниже и там кликну на [..], то всё отрабатывает как надо, почему так?

Почему первоначально в listbox-е два [..], так не должно быть, верно?
Название: Direct.png
Просмотров: 202

Размер: 4.4 Кб
0
COM‐пропагандист
781 / 734 / 143
Регистрация: 18.12.2014
Сообщений: 2,084
Записей в блоге: 4
17.09.2023, 16:30 4
Если у вас не 16‐битная программа, то функцию OpenFile следует забыть:
Обратите внимание! на то, что эта функция предусматривается только для совместимости с 16-разрядными версиями Windows. Новые приложения должны использовать функцию CreateFile.
Цитата Сообщение от Liss29 Посмотреть сообщение
0x37
Что это?
0
130 / 33 / 4
Регистрация: 18.11.2012
Сообщений: 1,412
18.09.2023, 00:27  [ТС] 5
Цитата Сообщение от Замабувараев Посмотреть сообщение
Что это?
Это атрибуты файлов или каталогов, добавляемых в список. У автора это указано как число.
C++
1
2
DWORD dwStyle = DDL_ARCHIVE | DDL_DIRECTORY | DDL_READONLY | DDL_HIDDEN | DDL_SYSTEM | 
                    DDL_READWRITE;
Цитата Сообщение от Замабувараев Посмотреть сообщение
Если у вас не 16‐битная программа, то функцию OpenFile следует забыть:
А какие параметры нужно задать CreateFile(...) чтобы при клике на каталоге функция возвращала -1, OpenFile(), например, это делает.

Я всё же не пойму одну вещь, если я запускаю программу из каталога в котором она находится(каталог HEAD), то это что, корневой каталог, почему не хочет подниматься в каталог уровнем выше? При условии, что программа находится не в корневом каталоге не C:\dir, D:\, а гораздо глубже, скажем D:\MyFolder\Документы\__Projects\Petzold\HEAD, почему не хочет идти в папку Petzold, если я кликаю по [..]?

Если же я спущусь на уровень ниже, то всё хорошо функционирует, если клацнуть на [..], то иду в каталог уровнем выше и OpenFile отрабатывает как надо, возвращает -1, если клацнуть на каталоге...

Ну и..., почему всё же два [..] в каталоге из которого запущена программа, что это значит?
0
130 / 33 / 4
Регистрация: 18.11.2012
Сообщений: 1,412
21.09.2023, 00:25  [ТС] 6
А что делать с чтением из файла и выводом, выводится какая-то ерунда, иероглифы. Если файл в кодировке UTF16-LE с BOM, то всё отлично читается и выводится, но если ansi или UTF8 с BOM, то читаются иероглифы. Буфер у меня объявлен как
Код
static TCHAR szReadBuffer[MAXREAD]
значит TCHAR == UNICODE в данном случае, и что делать, как-то этот процесс возможно автоматизировать чтобы кодировку не в ручную менять в редакторе, а чтобы всё это дело происходило в коде?
0
237 / 89 / 24
Регистрация: 07.01.2023
Сообщений: 354
23.09.2023, 10:35 7
Цитата Сообщение от Liss29 Посмотреть сообщение
как-то этот процесс возможно автоматизировать чтобы кодировку не в ручную менять в редакторе, а чтобы всё это дело происходило в коде?
Так есть чудесные функции GetStringTypeW, MultiByteToWideChar и WideCharToMultiByte. Используйте их
0
265 / 108 / 18
Регистрация: 26.12.2010
Сообщений: 450
24.09.2023, 22:01 8
-1 свидетельствует об ошибке (HFILE_ERROR ) , поэтому идет проверка на это значение. Это как if !(INVALID_HANDLE_VALUE != CreateFile).

А вообще, не юзайте эти древние апи.
0
130 / 33 / 4
Регистрация: 18.11.2012
Сообщений: 1,412
24.09.2023, 23:58  [ТС] 9
Цитата Сообщение от Azathtot Посмотреть сообщение
Так есть чудесные функции GetStringTypeW,
Не понял, что в ней чудесного, а по поводу функций преобразования MultiByteToWideChar и WideCharToMultiByte, то я их пробовал применять, но, если в массив считались символы в виде иероглифов, то толку от этих функций нет. Поэтому и спрашивал, можно ли определить кодировку файла в ходе выполнения программы чтобы понять, какой буфер использовать с char* или wchar_t*. Ответ нашёл, нет нельзя.

Добавлено через 3 минуты
Цитата Сообщение от Morgot Посмотреть сообщение
А вообще, не юзайте эти древние апи.
CreatrFile() древняя API?!
Пробовал и так и так т.е. и те и те функции результат один. Я пытался сохранить ту логику приложения, которую первоначально задал автор, не хотелось менять что-то кардинально.
0
COM‐пропагандист
781 / 734 / 143
Регистрация: 18.12.2014
Сообщений: 2,084
Записей в блоге: 4
25.09.2023, 07:31 10
Цитата Сообщение от Liss29 Посмотреть сообщение
можно ли определить кодировку файла
По метке BOM можно определить юникодную кодировку.
Смотрим первые байты файла.
EF BB BF — это кодировка UTF-8
FE FF — кодировка UTF-16 BE
FF FE — кодировка UTF-16 LE
00 00 FE FF — кодировка UTF-32 BE
FF FE 00 00 — кодировка UTF-32 LE

Если нет, значит это ASCII кодировка.
0
237 / 89 / 24
Регистрация: 07.01.2023
Сообщений: 354
25.09.2023, 13:36 11
Цитата Сообщение от Liss29 Посмотреть сообщение
то я их пробовал применять, но, если в массив считались символы в виде иероглифов
рукалицо.....
При чем тут "символы в види иероглифов"?
Вы считываете ПОСЛЕДОВАТЕЛЬНОСТЬ БАЙТ. А уже работой с многобайтными кодировками приводите ее к последовательности СИМВОЛОВ.
0
130 / 33 / 4
Регистрация: 18.11.2012
Сообщений: 1,412
26.09.2023, 00:49  [ТС] 12
Цитата Сообщение от Azathtot Посмотреть сообщение
При чем тут "символы в види иероглифов"?
А при том. Если строка считана в память в таком виде, то после преобразований с помощью вышеперечисленных функций ничего толкового, членораздельного, вменяемого, что можно прочитать не получается.
0
COM‐пропагандист
781 / 734 / 143
Регистрация: 18.12.2014
Сообщений: 2,084
Записей в блоге: 4
26.09.2023, 07:15 13
В файле нет строк, в файле байты.
0
265 / 108 / 18
Регистрация: 26.12.2010
Сообщений: 450
26.09.2023, 16:20 14
Liss29, CreateFile нормальная, OpenFile древняя
поменяйте на INVALID_HANDLE_VALUE != CreateFile, будет та же логика
0
130 / 33 / 4
Регистрация: 18.11.2012
Сообщений: 1,412
27.09.2023, 08:48  [ТС] 15
Цитата Сообщение от Morgot Посмотреть сообщение
CreateFile нормальная
Я же написал, что пробовал так и так, хотя ваша правда, условие не совсем так проверял, когда использовал CreateFile().
if(hFile != INVALID_HANDLE_VALUE), но если возвращалось единица, то что, получалось, что условие выполнялось не правильно, но с этим я разобрался. Я же спрашивал почему в листбокс выводится два [..] в этом и была проблема? после её устранения заработало и с CreateFile() и с OpenFile(). Правда возникла другая проблема.
0
27.09.2023, 08:48
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
27.09.2023, 08:48
Помогаю со студенческими работами здесь

OpenFile и runtime error 216
var hFile : Thandle; oBuff : _OFSTRUCT; wCount : Cardinal; tText : string; begin tText :=...

Что значит 2-й параметр функции OpenFile?
Какие значения он может принимать и что каждое значение значит.

Как использовать OpenFile, ReadFile и WriteFile
День всем добрый! Пока повышал своё консольное приложение до оконного, заметил проблему. Если...

Visual Studio 2008, WinAPI - Openfile
Подскажите, как используеться функция GetOpenFileName . НУ или скажу так. Мне нужно чтобы вылез...

Можно ли API функцией OpenFile запустить exe?
я попробовал результат 0, но я мог что-то не так сделать, я не пойму что за 2-й параметр у этой...

Использование DiscUtils. NotImplementedException при вызове OpenFile
подключил библиотеку https://github.com/breezechen/DiscUtils , не могу скопировать файл из Squash....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru