
Новичок
Профиль
Группа: Участник
Сообщений: 19
Регистрация: 27.9.2005
Репутация: нет Всего: нет
|
Пишу драйвер (по учебе надо) и застрял... не знаю что и делать. Скачал доки, которые смог найти в инете. Это три файла с кривым переводом. В начале написано: Авторский коллектив "*.*" и СП "Интерквадро". Так вот... С++ я знаю пока не очень хорошо, поэтому писал все по примерам из прилагающихся файлов к TVision. У меня код драйвера написан (не полностью) на асме и должен вызываться из проги на С++. Вот вопросы на которые я не смог найти ответ, а время поджимает: 1. Как обновлять строку главного меню и строку состояния и вообще как манипулировать ими. 2. Что такое палитра и как ей пользоваться (этот вопрос не так важен) для раскраски окон. 3. Как мне получить событие от клавиатуры и вообще я хотел бы выйти обратно в процедуру main после того как пользователь нажал клавишу Enter и выбрал один из пунктов меню. Потому, что я окончательно запутался в коде и хотел бы все сделать на чистом Си без ООП. Т. е. есть какая-нибудь функция, которая позволяет завершить приложение, наподобии нажатия Alt-X. Может событие какое-нибудь подобное использовать? Может кто-нибудь сможет мне помочь. В инете ничего не нашел путевого. Может книга какая есть хорошая. Короче нужны доки по TVision. Вот код проги из которой вызывается драйвер: | Код | #define Uses_TEventQueue #define Uses_TEvent #define Uses_TApplication #define Uses_TKeys #define Uses_TRect #define Uses_TMenuBar #define Uses_TSubMenu #define Uses_TMenuItem #define Uses_TStatusLine #define Uses_TStatusItem #define Uses_TStatusDef #define Uses_TDeskTop #define Uses_TDialog #define Uses_TStaticText #define Uses_TButton #define Uses_TRadioButtons #define Uses_TSItem #define Uses_TLabel
#include <tv.h> #include <stdlib.h> #include <string.h> #include <conio.h> #include <stdio.h>
const int cmAboutWin = 200; const int cmMainWin = 201;
extern "C" void far strat(); extern "C" void far interr();
/* -------------------------------------------------------- */ /* Структуры запросов к драйверу. */ /* -------------------------------------------------------- */
//--------------------------------------------------------- // Определение некоторых полезных типов typedef unsigned char BYTE; typedef unsigned int WORD; typedef unsigned long DWORD; //---------------------------------------------------------
/* Заголовок буфера запроса к драйверу, общий для всех команд */
struct _RH { BYTE size; // Длина буфера запроса. BYTE unit; // Номер устройства (для блочных). BYTE cmd; // Код команды (0x00 - 0x19). WORD status; // Слово состояния (заполняется драйвером). BYTE reserved[8]; // Зарезервировано. };
/* Команда инициализации, cmd = 0 */
struct _R0 { _RH rh0; // Фиксированный заголовок. BYTE nunits; // Число обслуживаемых устройств (для блочных). DWORD end_addr; // Дальний адрес нижней границы резидентной части. DWORD parm; // Адрес строки с параметрами из config.sys (для блочных). BYTE drive; // Номер диска (для блочных). BYTE msg_flag; // Сообщение об ошибке (0x0000, если ошибки не было). } r0;
/* -------------------------------------------------------- */ /* Определение класса TMyApp. */ /* -------------------------------------------------------- */
class TMyApp : public TApplication { public: TMyApp();
// Перегрузка метода initStatusLine класса TProgram. // Вследствии чего меняется вид строки состояния. static TStatusLine *initStatusLine(TRect r);
// Перегрузка метода initMenuBar класса TProgram. // Вследствии чего меняется вид строки главного меню. static TMenuBar *initMenuBar(TRect r);
// Перегрузка метода hanldeEvent, отвечающего за обработку // событий. virtual void handleEvent(TEvent& event);
// Свои методы. void AboutWindow(); void MainWindow(); void RunCommand(int Command); void SendRequest(void far *Req); void ShowRequest(int fl); char *MakeSTbl(char *s, int len_s); };
/* Конструктор TMyApp. */
TMyApp::TMyApp() : TProgInit( &TMyApp::initStatusLine, &TMyApp::initMenuBar, &TMyApp::initDeskTop ) { // Вывести главное окно. MainWindow(); }
class TMainWindow : public TDialog { public: TMainWindow(const TRect& bounds, const char *aTitle); virtual TPalette& getPalette() const; };
#define cpBlueWindow "\x20\x02\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F"\ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F"
TPalette& TMainWindow::getPalette() const { static TPalette palette(cpBlueWindow, sizeof(cpBlueWindow) - 1); return palette; }
TMainWindow::TMainWindow(const TRect& bounds, const char *aTitle) : TDialog(bounds, aTitle), TWindowInit(&TMainWindow::initFrame) { growMode = 0; dragMode |= dmLimitAll; options |= ofCentered; flags = wfMove | wfClose; }
/* Интерфейс с драйвером */
void TMyApp::SendRequest(void far *Req) { asm { les bx,Req } strat(); interr(); }
/* Функция добавляет справа к строке s1 таблицы длиной len_s символов, пробелы и символ |. Строка таблицы должна содержать символ табуляции \t. */
char *TMyApp::MakeSTbl(char *s, int len_s) { int i, ls1;
ls1 = strlen(s); for (i = 0; i < len_s - ls1; i++) strcat(s, " "); i = strlen(s); s[i - 8] = '|'; s[i - 8 + 1] = '\0';
return s; }
void TMyApp::ShowRequest(int fl) { int i, ls; char bufs[256]; char *ps;
clrscr(); strcpy(bufs, "+---------------------------------------+\n"); ls = strlen(bufs); // Вычислить длину таблицы. printf(bufs); printf("| Команда инициализии |\n"); printf("+---------------------------------------+\n"); if (fl) printf("| Входные параметры: |\n"); else printf("| Выходные параметры: |\n"); // size sprintf(bufs, "|\tsize = 0x%.2X", r0.rh0.size); ps = MakeSTbl(bufs, ls); strcat(ps, "\n"); printf(ps); // unit sprintf(bufs, "|\tunit = 0x%.2X", r0.rh0.unit); ps = MakeSTbl(bufs, ls); strcat(ps, "\n"); printf(ps); // cmd sprintf(bufs, "|\tcmd = 0x%.2X", r0.rh0.cmd); ps = MakeSTbl(bufs, ls); strcat(ps, "\n"); printf(ps); // status sprintf(bufs, "|\tstatus = 0x%.4X", r0.rh0.status); ps = MakeSTbl(bufs, ls); strcat(ps, "\n"); printf(ps); // reserved
sprintf(bufs, "|\treserved = 0x"); /*
for (i = 0; i < 8; i++)
printf("%.1X", r0.rh0.reserved[i]);
printf(" |\n"); */ }
void TMyApp::RunCommand(int Command) { switch(Command) { case 1: // Заполнить буфер запроса для команды cmd = 0, memset(&r0, 0, sizeof(r0)); r0.rh0.size = sizeof(_R0); // вывести на экран его содержимое ShowRequest(1); // и послать драйверу. SendRequest(&r0); ShowRequest(0); break; } }
/* Вывод главного окна */
void TMyApp::MainWindow() { TMainWindow *wnd = new TMainWindow(TRect(20, 4, 60, 17), "Выбор команды драйвера"); TRadioButtons *b = new TRadioButtons(TRect(3, 3, 30, 6), new TSItem("~1.~ Инициализация", new TSItem("~2.~ Неразрушающий ввод", new TSItem("~3.~ Вывод", 0) ))); wnd->insert(b); wnd->insert(new TLabel(TRect( 2, 2, 10, 3), "Команды", b )); wnd->insert( new TButton(TRect(15, 10, 25, 12), " OK", cmOK, bfDefault)); // Сохранить данные диалогового окна. deskTop->execView(wnd); if (b->mark(0)) RunCommand(1); if (b->mark(1)) RunCommand(2); if (b->mark(2)) RunCommand(3); destroy(wnd); }
/* -------------------------------------------------------- */ /* Перегрузка двух методов класса TProgram, отвечающих за */ /* строку состояния и главное меню. */ /* -------------------------------------------------------- */
/* Метод, отвечающий за строку состояния */
TStatusLine *TMyApp::initStatusLine(TRect r) { r.a.y = r.b.y - 1; // Сдвинуть в самый низ экрана return new TStatusLine( r, *new TStatusDef(0, 0xFFFF) + // Опредение элементов строки состояния *new TStatusItem("~Alt-X~ Выход", kbAltX, cmQuit) + // Определение действия клавиши F10 *new TStatusItem("~F10~ Меню", kbF10, cmMenu) + *new TStatusItem("~F4~ Выбор команды", kbF4, cmMainWin) + *new TStatusItem("~Alt-F3~ Закрыть", kbAltF3, cmClose) ); }
/* Метод, отвечающий за главное меню */
TMenuBar *TMyApp::initMenuBar( TRect r ) { r.b.y = r.a.y + 1; // Сдвинуть в самый верх экрана return new TMenuBar( r, *new TSubMenu("~Ф~aйл", kbAltF) + *new TMenuItem("~О~ программе...", cmAboutWin, kbF1, hcNoContext, "F1") + newLine() + *new TMenuItem("Вы~х~од", cmQuit, cmQuit, hcNoContext, "Alt-X") ); }
/* */ /* Обработчик событий класса TMyApp */ /* */
void TMyApp::handleEvent(TEvent& event) { TApplication::handleEvent(event);
if (event.what == evCommand) { switch (event.message.command) { case cmAboutWin: AboutWindow(); break; case cmMainWin: MainWindow(); break; default: return; } /* Очистить сообщение после обработки, т. е. присвоить ему значение evNothing. */ clearEvent(event); } }
/* -------------------------------------------------------- */ /* Окно About. */ /* -------------------------------------------------------- */
void TMyApp::AboutWindow() { TDialog *aboutBox = new TDialog(TRect(2, 2, 41, 15), "О программе..."); aboutBox->insert( new TStaticText( TRect(9, 2, 30, 9), "\003Эта программа\n\003\n" "\003демонстрирует работу\n\003\n" "\003заменяющего драйвера\n\003\n" "\003консоли CON" ) ); aboutBox->insert( new TButton(TRect(14, 10, 25, 12), " OK", cmOK, bfDefault) ); deskTop->execView(aboutBox); destroy(aboutBox); }
/* -------------------------------------------------------- */ /* Главная функция */ /* -------------------------------------------------------- */
int main() { TMyApp myApp; myApp.run(); return 0; }
|
Вот код асмовского драйвера, недописанный еще: | Код | public _strat, _interr .model small .code drv_con proc far ; ------------ Структуры команд ------------ ; ############ Фиксированный заголовок запроса ############ rh struc size_ db ? unit db ? cmd db ? status dw ? reserved db 8 dup (?) rh ends ; ############ Запрос для команды инициализации (cmd = 0) ############ rh0 struc _rh0 db size rh dup (?) nunits db ? end_addr dd ? parm dd ? drive db ? msg_flag db ? rh0 ends ; ------------ Заголовок драйвера ------------ next dd -1 ; Дальний адрес следующего загружаемого драйвера. attrib dw 8003h ; Слово атрибута. strateg dw _strat ; Адрес процедуры стратегии. interrupt dw _interr ; Адрес процедуры прерывания. dev_name db 'CON ' ; -------------------------------------------- Addr_Buf_Req dd ? ; Здесь процедура стратегии сохраняет ; адрес буфера запроса. sav db 0 ; Символ, считанный с клавиатуры. ;------------- Процедура стратегии ------------ _strat proc far mov word ptr Addr_Buf_Req,bx mov word ptr Addr_Buf_Req + 2,es ret _strat endp ;------------- Процедура прерывания ------------ _interr proc far ; Сохранить регистры. pushf ; Регистр флагов. push ds ; Сегментные регистры. push es
push ax ; Регистры общего назначения. push bx push cx push dx push di push si
; Восстановить адрес буфера запроса. lds si,Addr_Buf_Req ; ds:si - адрес запроса. mov bl,ds:[si].cmd ; В bl номер команды. xor bh,bh cmp bx,19h ; Если номер команды > 19h, jg unsupported ; перейти на обработчик. shl bx,1 ; Определить функцию драйвера. jmp word ptr cs:[tabl + bx]
; Таблица команд. tabl dw initialize ; 00h dw 4 dup (unsupported) ; 01h - 04h dw nondestruct_in ; 05h dw 2 dup (unsupported) ; 06h - 07h dw output_data ; 08h dw 17 dup (unsupported) ; 09h - 19h
unsupported: nondestruct_in: output_data:
; Выход. quit: ; Установить восьмой бит в слове состояния заголовка запроса. or ds:[si].status,0100h pop si pop di pop dx pop cx pop bx pop ax pop es pop ds popf retf
end_: ; Адрес конца резидентной части.
; ------------ Обработка команды инициализации ------------
initialize: ; Вернуть в поле end_addr адрес конца резидентной части. mov word ptr ds:[si].end_addr,offset end_ mov word ptr ds:[si + 2].end_addr,cs
push cs pop ds ; ds = cs. mov ax,0003h ; Очистить экран и int 10h ; установить режим 3.
; Издать сигнал из динамика. mov al,0B6h out 43h,al in al,61h or al,3 out 61h,al mov ax,5000 out 42h,al mov al,ah out 42h,al mov cx,0FFFFh loo: push cx mov cx,50h loo1: loop loo1 pop cx loop loo in al,61h and al,0FCh out 61h,al
; Вывод сообщения. mov ah,09h ; Вывести сообщение xor al,al ; о том, что драйвер lea dx,msg1 ; успешно int 21h ; установлен. jmp quit msg1 db "+----------------------------------------+",13,10 db "| Driver CON was installed successfully! |",13,10 db "+----------------------------------------+",13,10,'$'
_interr endp drv_con endp end
|
Помогите кто сможет разобраться или подкиньте доки ;)
|