Додаток OnlyOnce CBuilder

На рис 91 представлена ​​форма, яку ми будемо використовувати для програми OnlyOnce (ТолькоРаз) Як бачите, нічого особливого на формі немає на ній знаходиться єдина мітка статичного тексту, що говорить користувачеві не запускати другу копію Добре запамятайте цю форму, так як більше ми на неї дивитися не будемо

Коли ви створите новий додаток в CBuilder і форму, як на рис 91, закрийте форму Робота, яку нам потрібно зробити, проводиться не над формою, а над вихідним кодом програми

Виберіть команду View | Project Source з головного меню інтегрованого середовища CBuilder У редактор буде завантажений вихідний файл проекту (project1cpp) Подивіться на цей код, наведений у лістингу після рис 91

Рис 91 Форма додатка OnlyOnce

//———————————————————

#include &ltvcl\vclh&gt

#pragma hdrstop

//———————————————————

USEFORM(&quotUnit1cpp&quot,  Form1) USERES(&quotProject1res&quot)

//———————————————————

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)

{

try

{

Application-&gtInitialize()

Application-&gtCreateForm(__classid(TForm1),  &ampForm1) Application-&gtRun()

}

Пошук потрібної функції API catch (Exception & exception)

{

Application-&gtShowException(&ampexception)

}

return 0

}

Не так вже й багато можна сказати про цю процедуру Функція WinMain – Це точка входу для всіх Windows-додатків в будь-якої версії Windows Вона буде викликана при старті програми Насправді є ще частина глобального коду, яка запускається перед цією функцією (код, запускає додаток) Код, що запускає додаток, відповідає за створення обєкта Application Все подальше відбувається тут

Процес запуску додатка в CBuilder складається з трьох кроків По-перше, инициализируется обєкт Application Це важливо тільки в тому випадку, якщо ваша програма – сервер OLE Automation Якщо ваша програма – НЕ сервер, то можете видалити цю строчку з коду програми

Як тільки обєкт инициализирован, створюються всі форми, призначені для автоматичного створення Такі форми перераховані у вікні Project Manager (менеджер проектів) у системі CBuilder Зазвичай, якщо ви не вкажете зворотне, то всі форми, які ви додаєте в проект, позначаються системою як створювані автоматично (auto-create)

Навіщо вам може знадобитися відключити автоматичне створення форми Якщо ви пишете MDI-додаток, то вам не завжди потрібно, щоб дочірнє вікно MDI створювалося при запуску програми Або, може бути, ви не захочете, щоб форма була присутня в додатку, якщо це рідко використовується вікно діалогу, або ж у вас є набір форм, які за змістом виключають один одного під час роботи програми

Останній крок процесу – запустити програму Це робиться викликом методу Run обєкта Application в стартовому коді Цей виклик не повернеться назад, поки головна форма програми не буде закрита, чи не буде викликана функція Application-&gtTerminate()

Для того щоб не запускати другу копію додатку, нам потрібно не давати додатком створювати форми і не давати запускати метод Run Для цього ми спочатку повинні визначити при

запуску програми, чи є вже запущена копія додатку

У Windows API немає прямого методу пошуку програми У старі часи в Windows 31 існував параметр, переданий нашої функції WinMain, Який називається hPrevInstance (Посилання на попередню копію додатка), який можна було перевірити У програмах під Windows 95/NT цей параметр завжди буде дорівнювати NULL Проте можна знайти вікно з таким же заголовком, як і програма, яку ви намагаєтеся запустити Це робиться за допомогою функції FindWindowEx

Функція API FindWIndowEx має чотири параметри: імя класу вікна, заголовок вікна, а також два посилання, що ідентифікують дочірнє і батьківське вікно

Один або обидва параметри «імя класу» і «заголовок» можуть бути рівні NULL, А також один або обидва параметри, які містять посилання на вікна, можуть бути рівніNULL Якщо посилання на батьківське вікно дорівнює NULL, То пошук буде йти по всіх вікнам верхнього рівня (головним вікнам)

Що ми хочемо, так це всі вікна верхнього рівня, які мають таке ж імя, що і вікно нашої програми Додайте наступний код у функцію WinMain перед виразом try {, Яке запускає весь код обєкта Application:

HWND hWnd

hWnd = FindWindowEx(

NULL, / / ​​посилання на батьківське вікно NULL, / / ​​посилання на дочірнє вікно NULL, / / ​​покажчик на імя класу OnlyOne / / Імя вікна

)

if (hWnd = NULL)

{

BringWindowToTop(hWnd) return 0

}

Цей код буде шукати вікно з текстом «OnlyOne» серед вікон верхнього рівня Якщо функція FindWindowEx знайде таке вікно, то вона поверне посилання (handle) на це вікно (приблизно те ж саме, що і властивість FormHandle в CBuilder) У такому випадку ми використовуємо другу функцію API, BringWindowToTop, Для виносу цього вікна на передній план BringWindowToTop має один параметр – посилання на вікно, яке потрібно перемістити

Після переміщення старого додатки на передній план нам потрібно запобігти запуск нового Програма закінчує роботу, коли відбувається вихід з функції WinMain, Так що найпростіше виконати оператор return (повернення з функції) в цей момент Значення, яке ви повертаєте, традиційно є значенням, що повертається програмою, але використовується вона рідко, так що ми просто повертаємо 0

Не намагайтеся запускати це додаток з інтегрованого середовища CBuilder Закрийте CBuilder і потім запустіть програму з провідника Windows IDE системи CBuilder, схоже, тримає приховане вікно з заголовком нашої форми Коли функція FindWindowEx знайде це вікно, вона скаже вам про це, і ваш додаток ніколи не запуститься

От і все стосовно заборони на запуск другого копії вашої програми Ви тепер можете додавати цей код у всі ваші програми і більше не турбуватися про те, що програма може бути запущена двічі

Коли програмісти розмовляють про Windows 95 або Windows NT, вони часто говорять про перетягуванні (drag-and-drop), і вище в книзі ми розглядали

приклад перетягування даних між двома списками у формі Однак під drag-and-drop розуміється також і щось інше Програма Windows Explorer (провідник) дозволяє, як і інші, перетягувати файли в інші програми Іноді, наприклад, при перетягування файлу на іконку програми ця програма запускається з параметром – імям цього файлу В інших випадках це дія дозволяє вам обробляти файли, перетягуючи їх з провідника в працюючу програму У цьому прикладі ми якраз і розглянемо даний випадок

Обробка drag-and-drop повязана з трьома моментами По-перше, потрібно пояснити системі Windows, що на вашу програму можна перетягувати файли По-друге, потрібно обробляти повідомлення, які Windows посилає вам, коли файл «роняю» на вікно вашого додатки І нарешті, потрібно щось робити з цими перенесеної файлами

Система CBuilder підтримує деякі форми перетягування, але тільки усередині системи Якщо ви хочете обробити перетягування в системі CBuilder, то вам потрібно злегка поритися в Windows API (саме тому, звичайно, це і знаходиться в даній главі) Давайте подивимося на кожен шматочок окремо, щоб зрозуміти, що відбувається

Інформування Windows про те, що ваша програма приймає перетаскі ваемие файли, – досить проста задача Все, що потрібно, – один виклик API, функція DragAcceptFiles Ця функція API приймає два аргументи: посилання на вікно і логічний прапор Посилання – це посилання на вікно, на яке ви хочете дозволити «упускати» файли Логічне значення ж вказує, чи буде це вікно (true) чи ні (false) сприймати перенесені файли Очевидно, що перемикаючи це значення, ви можете дозволяти або забороняти перетягування під час роботи програми Я особисто жодного разу не зустрічав ситуації, в якій треба було б відключити дозвіл на перетягування, але, як мені здається, така ситуація можлива

Коли ви сказали системі, що ви сприймаєте перетягувати файли, наступний крок – чекати, поки не прийде повідомлення про те, що вам «притягли» файл Воно приходить у вигляді повідомлення WM_DROPFILES, що посилається вашої віконної функції У формі CBuilder ви можете додати функцію-обробник повідомлення Повідомлення WM_DROPFILES говорить вам про те, що система «упускає» один або більше файлів на ваше вікно, але воно не говорить вам, що це за файли Ваша робота як програміста – запитувати інформацію про кожен файл і відповідно його обробляти

Третій крок, обробка файлу, залежить від програми Може бути, вам потрібно відкрити файл і прочитати з нього дані Може, видалити його або скопіювати його кудись ще Що б вам не було потрібно, у вас буде імя файлу, з яким можна працювати Ваші дії з ним – ваш вибір

На рис 92 наведено форму, яку ми збираємося використовувати в прикладі додатки DragDropFiles На цій формі перебувати одне поле статичного тексту («Файли, перенесені сюди: »), кнопка, що закриває форму, і вікно списку для відображення файлів, які будуть перетягнути на форму У цьому прикладі ми нічого не робимо з даними, тільки

відображаємо для користувача імена файлів

Рис 92 Форма додатка DragDropFiles

Насамперед, як ми вже говорили, треба сказати системі, що вікно цієї форми буде приймати файли, перенесені на нього Створіть обробник події OnCreate для форми і додайте в метод FormCreate наступний код:

void __fastcall TForm1::FormCreate(TObject *Sender)

{

/ / Дозволити нашої формі приймати файли

DragAcceptFiles (Handle, TRUE)

}

Тут ми повідомляємо операційну систему про те, що будемо приймати файли, перенесені на форму (на це вказує аргумент функції, рівний TRUE)

Коли ми сказали Windows про те, що будемо обробляти перенесені файли, можна розслабитися і чекати, поки їх до нас не притягнуть Для цієї події ми чекаємо повідомлення WM_DROPFILES У класі TForm немає прямого обробника для цього повідомлення, так що нам потрібно додати елемент в карту повідомлень для форми, як ми робили в попередніх прикладах Додайте наступні рядки в заголовний файл для класу форми Ці рядки визначать новий обробник стандартного повідомлення Windows і потім звяжуть його з повідомленням WM_DROPFILES:

class TForm1 : public TForm

{

__published: // IDE-managed components TListBox *ListBox1

TLabel *Label1 TButton *Button1

void __fastcall Button1Click(TObject *Sender) void __fastcall FormCreate(TObject *Sender) private: // User declarations

void __fastcall HandleDropFiles(TMessage&amp Msg) public: // User declarations

__fastcall TForm1(TComponent *Owner) BEGIN_MESSAGE_MAP

MESSAGE_HANDLER(WM_DROPFILES,  TMessage,  HandleDropFiles)

END_MESSAGE_MAP(TForm)

}

Після того як ми описали процедуру, яка повинна робити всю роботу, залишилося тільки написати саму цю процедуру Давайте спочатку поглянемо на код, а потім зясуємо, як він працює: void __ fastcall TForm1 :: HandleDropFiles (TMessage & Msg)

{

/ / Отримати інформацію про перенесені з повідомлення

HDROP hDropInfo = (HANDLE)MsgWParam char  szFileName[_MAX_PATH]

int iFiles = DragQueryFile(hDropInfo, (DWORD)-1, (LPSTR)NULL, 0)

/ / Для кожного привезених файлу помістити його

/ / В масив Items списку

for (int nIdx = 0 nIdx &lt iFiles ++nIdx)

{

DragQueryFiles (hDropInfo, nIdx, szFileName, _MAX_PATH) ListBox1-&gtItems-&gtAdd (szFileName)

}

}

Спочатку ми отримуємо обєкт типу HDROP, Перетворюючи елемент повідомлення WParam  до цього типу HDROP насправді просто індекс списку перенесених файлів в системі Використовуйте посилання HDROP для отримання окремих файлів в блоці перенесених

Функція API DragQueryFile має два різних методу її використання (як, ви не любите такі функції) Якщо ви викличете її з індексом _1 і покажчиком, рівним NULL, то вона поверне вам кількість елементів у списку перенесеного Це і є кількість файлів, які користувач виділив в Windows Explorer і переніс на вашу програму Якщо ви не хочете дозволяти перетягувати відразу багато файлів за раз, то можете додати сюди код, який зупиняється, якщо кількість файлів більше 1 Зауважте, що ви ніколи не отримаєте це повідомлення, якщо список порожній

Коли у нас є декілька файлів в списку, вступає в гру другий варіант використання функції DragQueryFile Якщо ви передасте нормальний індекс (другий аргумент функції) і буфер для зберігання отриманого імені файлу, то функція передасть вам імя кожного файлу в списку Як ви памятаєте, Explorer працює з довгими іменами файлів, так що нам потрібно мати буфер, достатній для розміщення імені файлу, перенесеного на наше вікно Макрос

_MAX_PATH, Визначений у системних заголовних файлах, визначає розмір, гарантиро ванно достатній для зберігання будь-якого імені файлу (до 256 символів), яке використовується в системі Windows Однак як перевірки ми передаємо цю довжину в функцію API, щоб, у разі несумісності в майбутньому (якщо імена файлів стануть довшими), програма не руйнувалася

У нашому прикладі все, що нам потрібно зробити з іменами файлів, – це додати їх у наш список Потім користувач, наприклад, може вибрати декілька файлів з цього списку і застосувати до них яку-небудь дію або що-небудь ще, що потрібно вашому додатком Цей приклад досить простий і нічого більше з файлами не робить, окрім як відображає їх імена у списку Останній штрих – обробити натискання на кнопку закриття, розташовану внизу форми Створіть обробник натискання на кнопку і додайте в метод Button1Click форми наступний код:

void __fastcall TForm1::Button1Click(TObject *Sender)

{

Application-&gtTerminate()

}

Рис 93 Форма додатка DragDropFiles в дії

Як бачите, обробка перетягування файлів з Windows Explorer дуже проста Щоб побачити, як це працює, запустіть програму і викличте Windows

Explorer Виберіть кілька файлів у вашому каталозі і перетягніть їх (утримуючи ліву кнопку миші на вибраному файлі і переміщаючи мишу за межі вікна) на працююче додаток Відпустіть ліву кнопку миші і подивіться, які імена файлів зявляться у вікні списку

На рис 93 приведено вікно програми з кількома файлами, перетягнути вими з вікна Windows Explorer Як бачите, у списку зявляються повні імена файлів (з шляхом), то є додаток точно знає, що за файли було вибрано користувачем і перетягнути на форму

Джерело: Теллес М – Borland C + + Builder Бібліотека програміста – 1998

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*