Архив

Архив раздела ‘Кусочки кода’

SendMessage в Windows::Forms под Visual C++ 2010

24 февраля 2011 5 комментариев

Возникла необходимость заюзать winapi-шную функцию в приложении Windows Forms на C++

Я потратил около шести часов, чтобы найти решение, потому что просто так написать

SendMessage(Handle, WM_CLOSE, 0, 0);

не достаточно. А интуицией догадаться может только экстрасенс.

Короче. В файл stdafx.h после тудушечки добавляем инклюд:

// TODO: Установите здесь ссылки на дополнительные заголовки...
#include "windows.h"

В свойствах проекта идем в Свойства конфигурацииКомпоновщикВвод, щелкаем по свойству Дополнительные зависимости (у правильных пацанов это называется Linker – Input – Additional dependencies) и выбираем из раскрывающегося списка <наследовать от родителя или от свойств проекта по умолчанию>. Возможно, придется выбрать пункт <Изменить...> и поставить там галку:

И только теперь мы можем вызывать тот же SendMessage(), но с обязательными предшествующими двойными двоеточиями и преобразованием численного значения указателя к структуре HWND. Вот так:

::SendMessage((HWND)this->Handle.ToInt32(), WM_SYSCOMMAND, SC_MONITORPOWER, 2);

Ура! И главное совершенно очевидно, особенно с настройкой проекта.

Метки: , ,

Прогресс копирования файла (CopyFileEx и ProgressBar)

29 ноября 2010 Нет комментариев

При копировании объемных файлов функцией CopyFileEx() [1] возможно сообщать пользователю о прогрессе выполнения операции, при помощи callback-функции (обратного вызова). Например, посредством прогрессбара (полоски загрузки).

Помимо вызова функции CopyFileEx() необходимо написать реализацию колбэк-функции. Допустим, что на форме Form1 у нас есть компонент ProgressBar1, в котором мы и планируем отображать прогресс копирования, тогда реализация выглядит следующим образом:

DWORD CALLBACK ProgressRoutine(
    LARGE_INTEGER TotalFileSize,
    LARGE_INTEGER TotalBytesTransferred,
    LARGE_INTEGER StreamSize,
    LARGE_INTEGER StreamBytesTransferred,
    DWORD dwStreamNumber,
    DWORD dwCallbackReason,
    HANDLE hSourceFile,
    HANDLE hDestinationFile,
    LPVOID lpData
)
{
    // изменяем тукущую позицию
    Form1->ProgressBar1->Position =
        Form1->ProgressBar1->Max * TotalBytesTransferred.QuadPart 
            / TotalFileSize.QuadPart;
    return PROGRESS_CONTINUE;
}

Теперь при вызове функции CopyFileEx() нам достаточно лишь передать ей имя колбэк-функции.

// здесь храним пути к исходному файлу и месту назначения копирования
const char *FileFrom = ("c:\\somewhere\\file.txt").c_str();
const char *FileTo   = ("\\server\\pub\\pepyaka.ololo").c_str();
 
// включаем обработку сообщений для того, чтобы видеть изменения прогрессбара
Application->ProcessMessages();
 
// копируем с флагом защиты от перезаписи
bool copied = CopyFileEx(FileFrom, FileTo, ProgressRoutine,
    NULL, 0, COPY_FILE_FAIL_IF_EXISTS);
 
// по значению переменной copied можно судить об успехе операции
if (copied == true) ShowMessage("Всё отменно скопировалось");

При возникновении ошибок поможет функция GetLastError() [2], которая вернет код подседней ошибки WINAPI. Значение кода поможет понять этот список.

Метки: , , ,

Подсказки в строке состояния

12 августа 2010 Нет комментариев

Задача:
При наведении мыши на определенный контрол, выводить подсказку о его назначении в строке состояния (StatusBar).

Решение:
С первого взгляда на проблему хочется тут же взяться и начать писать обработчики событий OnMouseEnter и OnMouseLeave вроде этих:

void __fastcall TForm::SomeControlMouseEnter(TObject *Sender)
{
    // Выводим сообщение в строку состояния
    StatusBar1->SimpleText = "Вы навели мышь на вот этот контрол";
}
//---------------------------------------------------------------------------
void __fastcall TAddNewLocationForm::BInsertMouseLeave(TObject *Sender)
{
    // Очищаем строку состояния
    StatusBar1->SimpleText = "";
}

Конечно, это вполне работоспособный код, но если обработать таким образом нужно много элементов на форме, сразу задумываешься: а нет ли способа покороче да поуниверсальнее.

Мы может воспользоваться компонентом ApplicationEvents (группа Additional в BDS 2006), отвечающим за обработку событий приложения. Нам пригодится событие OnHint.
Оно возникает, когда курсор мыши перемещается над компонентом или элементом меню. При этом значение свойства Hint текущего компонента заносится в одноименное свойство приложения: Application->Hint.

Cначала задайте текст подсказок в свойстве Hint требуемых контролов. Дальше пишем простой обработчик события OnHint:

void __fastcall TForm::ApplicationEvents1Hint(TObject *Sender)
{
    StatusBar1->SimpleText = Application->Hint;
}

Собственно, всё. Теперь при наведении мыши на компоненты, в статусной строке будут возникать подсказки, соответствующие данному компоненту.

Задача решена.

Доступ к элементам TRadioGroup

5 августа 2010 Один комментарий

Если вы когда-нибудь пользовались компонентом TRadioGroup, то, пожалуй, знаете, насколько он удобен при динамическом формировании списка переключателей. Всего-то и нужно, что добавлять и удалять строки списка типа TStringList

RadioGroup1->Items->Clear();              // удаление всех элементов
RadioGroup1->Items->Add("Первая точка");  // добавление новых
RadioGroup1->Items->Add("Вторая точка");

Ну и конечно же, вы знаете, что определить выбранную точку можно по значению свойства ItemIndex. Нумерация начинается с нуля, как заведено.

А вот вопрос: как получить доступ к свойствам отдельных элементов, сперва вызывает проблемы. На самом деле всё просто, нужно использовать массив Controls. Вот доступ к выделенному элементу:

int idx = RadioGroup1->ItemIndex;            // запоминаем индекс
RadioGroup1->Controls[idx]->Enabled = false; // делаем недоступным
RadioGroup1->Controls[idx]->Visible = false; // скрываем

Ну и так далее.

Для обхода всех элементов, воспользуемся циклом, взяв количество элементов из свойства ControlCount:

for (int i = 0; i < RadioGroup1->ControlCount; i++)
    RadioGroup1->Controls[i]->Caption = IntToStr(i) + "-й элемент";

В результате все элементы списка будут переименованы.

Так же не забывайте про методы BeginUpdate() и EndUpdate(), которые позволят избежать мерцания списка при изменении состава элементов.

RadioGroup1->Items->BeginUpdate(); // отключаем обновление элементов
for (int i = 0; i < RadioGroup1->ControlCount; i++)
    RadioGroup1->Controls[i]->Caption += "(" + IntToStr(i) + ")";
RadioGroup1->Items->EndUpdate();   // включаем обратно
Метки: , ,

Получить имена файлов в папке

Сканировать определенную папку и получить имена всех или определенных файлов вам позволит следующий код:

int ires;
TSearchRec SR;
AnsiString ext; // Расширение.
 
// Очищаем список файлов в компоненте ListBox
List->Clear();
// Задаем параметры поиска: где искать и что.
ires = FindFirst("C:\\*.*", faAnyFile | faArchive, SR);
while (ires == 0)
{
    // Если нужны только определенные типы файлов,
    // то ведем проверку по расширению.
    ext = ExtractFileExt(SR.Name);
    if ((ext == ".bmp") || (ext == ".jpg")) {
        // Заносим имена файлов в список.
        List->Items->Add(SR.Name);
    }
    // Переход к следующему файлу к каталоге.
    ires = FindNext(SR);
}
// Поиск завершен.
FindClose(SR);

Основан на функциях Find.

int FindFirst (AnsiString Path, int Attr, TSearchRec & F);

Находит первый файл с заданными атрибутами в указанном каталоге.
Атрибуты передаются с помощью следующих констант: faReadOnly, faHidden, faSysFile, faVolumeID, faDirectory, faArchive.

В последний аргумент функции заносится результат поиска.

Метки: , ,

Новая рубрика: Кусочки кода

Давольно давно искал место, куда бы сваливать всякие полезные куски кода. Ведь как бывает: сталкиваешься с новой областью в программировании, начинаешь изучать. Находишь решение. И хочется, чтобы это решение не потерялось, чтобы его можно было быстро взять, если понадобиться в следующем проекте.

Сначала хотел создать отдельный сайт, но поленился, и сделал эту рубрику.

Встречайте. Code Chips — «Кусочки кода».

Первая запись про то, как преобразовать картинку jpeg в формат bmp в C++ Builder.

Метки:

Конвертировать JPEG в BMP

Функция конвертирует файл формата jpeg в bmp.
На входе полное имя файла, возвращает true в случае успешной конвертации.

bool JPEG2BMP(AnsiString FileName)
{
    TJPEGImage        *jpg = new TJPEGImage;
    Graphics::TBitmap *bmp = new Graphics::TBitmap;
    bool ok = true; // Маркер хорошего поведения.
 
    try {
        jpg->CompressionQuality = 100; // Качество сжатия.
        jpg->LoadFromFile(FileName);   // Загружаем jpeg.
        try {
            bmp->Assign(jpg);          // Переносим данные в bmp.
            bmp->SaveToFile(ChangeFileExt(FileName, ".bmp"));
        } catch (...) {
            ok = false;
        }
    } catch (...) {
        ok = false;
    }
    jpg->Free();
    bmp->Free();
    return ok;
}

Для информирования пользователя об ошибке можно добавить перед return что-то из ряда:

if (!ok)
    ShowMessage("Конвертирование не увенчалось успехом");
Метки: , , ,