Все технические форумы на одном сайте Удобный поиск информации с популярных форумов в одном месте
Вопрос: Примеры к книге "Архитектура приложений"

Добрый день. Есть многим известная книга Мартина Фаулера "Архитектура приложений". Подскажите, пожалуйста, где можно найти к практическим главам (когда пишет о "Unit of Work", "Data Mapper" и т.п.) примеры исход. текстов, например, на JAVA . Это позволило бы в том же Eclipse их прокручивать и это было бы гораздо понятнее и нагляднее.
Ответ:
Цитата(Stolzen @  18.6.2014,  13:02 )
В принципе я не думаю, что умение реализовывать именно эти паттерны Фаулера имеет большое значение, ведь почти все в джаве уже есть реализованное. Поэтому в данном случае (имхо) практичнее следовать от частного к общему, т.е. научиться пользоваться какой-нибудь библиотекой, а потом попробовать понять, какие паттерны в ней реализованы. 

Спасибо за совет
Вопрос: Отсутствует шаблон "консольное приложение"

всем привет Помогите надо пункт "консольное приложение" установил VS а его нету.


Добавлено через 2 часа 5 минут
установил " ru_visual_studio_express_2012_for_windows_8_x86_x64_dvd_920678 "
А вообще мне надо " Microsoft Visual Studio Express 2013 Editor " ОСWindows 8.1 у меня . Помогите.
Ответ: Спасибо 2013 подошла.
Вопрос: Дональд Кнут "искусство программирования" - насколько применимо на практике?

Когда я что-то изучаю, всегда начинаю с самых основ, что бы понимать все до мельчайших подробностей. Мне хочется научиться не просто писать код, а решать алгоритмические задачи, научиться оптимизировать программу под конкретную ЭВМ, будь то центральный процессор, видеокарта или контроллер от микроволновки. В свете этого труд Кнута показался лучшим решением для изучения программирования.

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

Что могут посоветовать опытные программисты? Имеют ли место вышеобозначенные опасения, или книга Кнута - действительно лучший выбор для меня?
Ответ: Можно сначала изучить ассемблер Кнута и получить представление как эти все ассемблеры для фон Неймановской архитектуры устроены. А затем посмотреть - нужно ли их учить, или более высокоуровневыми языками, используемыми в разного рода "микроволновках" (Например С). Зная любой ассемблер программировать на высокоуровневом языке проще.
Вопрос: как написать простейший пример "Hello World" на C++ в Visual Studio 2008?

Всем привет.
Подскажите пожалуйста, как написать простейший Hello World на C++ в Visual Studio 2008?
Я создаю проект кансольного приложения win32, пишу в файле main.cpp следующий код:
Код C++
1
2
3
4
5
6
#include"stdafx.h"
#include<iostream.h>
void main() {
cout<<"Hello World!"<<;
return0;
}
Извиняюсь, может немного не так написал. Просто я в c++ пока чайник, до сели работал лишь с javascript и php.
Ну примерно так.
Но он не хочет компилироваться. Пишет, что файла iostream.h нету.
Подскажите кто-нибудь, как можно грамотно написать простой Hello World?
А от него я уже оттолкнусь.
Ответ: Eugene13, Спасибо за отзыв. Насколько я понял из содержимого файла std_lib_facilities.h, в него входит список от iostream до stdexpert. И раз подключив std_lib_facilities.h, остальные можно уже не подключать? It provides the most common standard headers (in the global namespace) and minimal exception/error support.

А все таки, почему рекомендация в книге столь настоятельна. Связано ли это с чем то особенно значимым или же это издержки версии Visual Studio и времени написания книги? Спасибо.
Вопрос: Разработать программный модуль "Книжный магазин". Что конкретно сделать?

Разработать программный модуль "Книжный магазин", который содержит сведения про книги (...). Покупатель оформляет заявку на нужные ему книги, а если таких нет, то он заносится в базу и оповещается, когда нужные ему книги поступают в магазин.
Вопрос такой. Я должен сделать какое-то клиентское приложение, которое будет взаимодействовать с базой данных или что попроще?
Вообще тема не должна быть в разделе "Delphi", но я не понимаю как это исправить.
Ответ:
Сообщение от Unoffe
Вопрос такой. Я должен сделать какое-то клиентское приложение, которое будет взаимодействовать с базой данных или что попроще?
Ну, так проще всего.
Для начала решите для себя, где будут храниться данные - в базе(лечше всего), в файле, вводиться пользователем в массив(хуже всего).
Вопрос: Книжка "Технология программирования на C++. Win32 API приложения" (Литвиненко)

Ищу данную книгу в электронном виде и в отличном качестве, а то все, что разбросано по сети имеет ужасный вид...

Также помогите пожалуйста с определением книг по Win API через С++. Поиск по форуму дал очень немного информации про это, да и те варианты, что были - про общее понятие Win API... Хотелось бы именно через парадигму С++ про это читать.

Буду рад за помощь!
Ответ: Да, наверное, книга А. Побегайло и имелась в виду.
Вопрос: Приложение "Книжный магазин"

напишите программу пожалуйста книжный магазин и если не сложно пришлите мне в архиве программу( очень вас прошу ,если не сложно кто поможет мне
книжный магазин, который содержит сведения о книгах (автор, название, издательство, год издания), Покупатель оформляет заявку на нужные ему книги, если таковых нет, он заносится в базу и оповещается, когда нужные книги поступят в магазин.
Ответ:
Сообщение от Анютка98
магазин и если не сложно
Сообщение от Анютка98
прошу ,если не сложно

Не по теме:

когда я начинаю писать какой нибудь проект, то я начинаю с внешней оболочки, проявляю свой креатив так сказать. То же самое советую и вам. Накидайте на форму компонентов. Разместите их так "красивенько". А потом уже пишите. Если что не знаете, идите искать в гугл, там уже все написано и описано что дальше не куда.
Возьмите в руки бумагу и напишите алгоритм действий пользователя. Удачи!

Вопрос: Создание форм авторизации и заставки (Splash-формы) в приложениях

Создание формы для авторизации в приложении.

Очень многие делают это совершенно неправильно: уже после того, как написано приложение добавляют еще одну форму, и хотят сделать так, чтобы сначала открывалась новая форма, а потом, когда пользователь введет пароль для входа в программу, скрыть ее и уже продолжать создавать формы как и раньше, до добавления формы авторизации. Это в корне неправильный подход. По нескольким причинам:
  1. Если при таком решении форма авторизации будет назначена главной формой приложения, ее потом нельзя будет закрыть, можно будет только скрыть, иначе при закрытии главной формы будет автоматически закрыто само приложение
  2. Главная (и все остальные) форма приложения вообще не должны создаваться до тех пор, пока пользователь не подтвердит своих прав на использование данного продукта. Иначе очень просто будет чуть более продвинутому пользователю показать уже созданную, но скрытую форму, чем если бы ее вообще еще не существовало

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

Решение очень простое: создаем форму авторизации, убираем ее из списка автоматически создаваемых (Project -> Options -> Forms, перенести форму из списка Auto-create в список Available)

На форме расположим 2 поля ввода (edUser для ввода логина и edPass для ввода пароля) и 2 кнопки (btnLogIn для подтверждения и btnCancel для отмены авторизации)

По нажатию на кнопку LogIn на форме авторизации либо просто проверяем соответствие пары логин/пароль:
C++
1
2
3
4
5
6
7
8
9
10
11
void __fastcall TForm3::Button1Click(TObject *Sender)
{
    if (edUser->Text == "volvo" && edPass->Text == "test")
    {
        ModalResult = mrOk; // в случае соответствия возвращаем один результат
    }
    else
    {
        ModalResult = mrCancel; // иначе - другой. Этот же результат - и по нажатию на кнопку Cancel
    }
}
, либо делаем чуть более интересно: пару логин/хеш пароля храним в Ini-файле, и при нажатии на LogIn проверяем соответствие:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void __fastcall TForm3::Button1Click(TObject *Sender)
{
    std::auto_ptr<TIniFile> ini (new TIniFile(ChangeFileExt(ParamStr(0), ".ini"))); // #include <IniFiles.hpp>
    std::auto_ptr<TIdHashMessageDigest5> hash(new TIdHashMessageDigest5); // #include <IdHashMessageDigest.hpp>
 
    if(ini->ReadString("users", edUser->Text, "") == hash->HashStringAsHex(edPass->Text, TIdTextEncoding::Default))
    {
        ModalResult = mrOk;
    }
    else
    {
        ModalResult = mrCancel;
    }
}
Разумеется, можно придумать еще много способов хранения паролей или их хешей, но основная идея этого поста - дать общее понимание того, что же делать с этой формой дальше, как ее показать, чтобы только после успешной аутентификации выполнение программы шло дальше.

Для этого в класс формы авторизации нужно добавить статический метод Execute:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class TForm3 : public TForm
{
__published:    // IDE-managed Components
    // ...
private:    // User declarations
public:     // User declarations
    __fastcall TForm3(TComponent* Owner);
    static bool __fastcall Execute(); // <--- Вот его описание
};
 
// а вот - реализация:
bool __fastcall TForm3::Execute()
{
    TForm3 *frm = new TForm3(0);
    int res = frm->ShowModal();
    delete frm;
    return res == mrOk; // вернуть признак успешной авторизации
}
А теперь открываем главный файл проекта (Project -> View source), и меняем порядок создания форм с того, что было раньше:
C++
1
2
3
4
5
6
         Application->Initialize();
         Application->MainFormOnTaskBar = true;
 
         Application->CreateForm(__classid(TForm1), &Form1);
         Application->CreateForm(__classid(TForm2), &Form2);
         Application->Run();
на такой:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
        if(TForm3::Execute()) // сначала показываем форму авторизации
        {
            // и только если результат авторизации успешен - создаем главную форму приложения
            Application->Initialize();
            Application->MainFormOnTaskBar = true;
            Application->CreateForm(__classid(TForm1), &Form1);
            Application->Run();
        }
        else
        {
            // иначе показываем сообщение о невозможности войти в программу,
            // и приложение завершается, не создавая никаких форм
            Application->MessageBox(
                _T("Вы не можете пользоваться приложением, так как не прошли авторизацию"),
                _T("Защита приложения")
            );
        }
Это самый простой метод авторизации, когда пользователь просто вводи свой логин/пароль, и в случае, если он ввел их правильно, он получает возможность использовать приложение. Чуть более интересно будет добиться того, чтобы в приложении было несколько групп пользователей, скажем, админ и просто пользователь. Тут тоже есть несколько вариантов реализации:
  1. Сделать одну форму, на которой в зависимости от некоего глобального флажка динамически создавать набор компонентов, нужный для представителя группы пользователей, к которой принадлежит залогинившийся (способ очень хорош тем, что на форме оказываются только необходимые данной группе пользователей компоненты, но для сложных форм с большим количеством компонентов на них создавать все динамически может быть долго по времени)
  2. Все так же сделать одну форму, но уже в дизайнере набросать на нее две группы компонентов (например, на разные вкладки TPageControl, или на разные TPanel), и по значению того же глобального флажка показывать одну вкладку (панель), и скрывать все остальные (этот способ гораздо проще, но теперь на форме, хоть и скрытыми, одновременно присутствуют все компоненты для всех групп пользователей, и все обработчики событий)
  3. Сделать разные формы для разных групп пользователей и создавать/показывать только нужную, остальные вообще не создавать.

Вариант №3 - самый оптимальный. Для его реализации нужно чуть-чуть изменить описание класса формы авторизации:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
enum AuthStatus {authNone, authUser, authAdmin}; // это список всех возможных групп пользователей
 
class TForm3 : public TForm
{
__published:    // IDE-managed Components
    TLabeledEdit *edUser;
    TLabeledEdit *edPass;
    TButton *btnLogin;
    TButton *btnCancel;
    void __fastcall btnCancelClick(TObject *Sender);
    void __fastcall btnLoginClick(TObject *Sender);
private:    // User declarations
public:     // User declarations
    __fastcall TForm3(TComponent* Owner);
    static AuthStatus __fastcall Execute();
    static AuthStatus status; // Добавляем флажок
 
};
AuthStatus TForm3::status = authNone; // инициализация статического поля класса
и реализацию обработчика клика по кнопке и метода Execute() :
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
void __fastcall TForm3::btnLoginClick(TObject *Sender)
{
    // разумеется, тут точно так же можно сделать проверку паролей
    // из INI-файла, только тогда в файле придется еще хранить
    // роль каждого пользователя в системе
    if (edUser->Text == "volvo" && edPass->Text == "test")
    {
        status = authAdmin;
        ModalResult = mrOk;
    }
    else
    if (edUser->Text == "nata" && edPass->Text == "second")
    {
        status = authUser;
        ModalResult = mrOk;
    }
    else
    {
        ModalResult = mrCancel;
    }
}
 
// ---------------------------------------------------------------------------
AuthStatus __fastcall TForm3::Execute()
{
    TForm3 *frm = new TForm3(0);
    TForm3::status = authNone;
    frm->ShowModal();
    delete frm;
    return TForm3::status; // Возвращаем статус пользователя
}
, и изменить главный файл приложения:
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
        AuthStatus st = TForm3::Execute(); // получаем статус пользователя
        if (st != authNone) // если авторизация была успешной
        {
            Application->Initialize();
            Application->MainFormOnTaskBar = true;
            switch (st)
            {
            case authAdmin: // залогинился админ - создаем админскую форму
                Application->CreateForm(__classid(TForm1), &Form1);
                // тут можно создать еще формы, которые нужны только админу
                break;
            case authUser: // простой пользователь - создаем пользовательскую
                Application->CreateForm(__classid(TForm2), &Form2);
                // те формы, которые нужны только для пользовательского аккаунта - можно создать здесь
                break;
            }
 
            // при необходимости - создаем другие общие формы здесь
            Application->Run();
        }
        else // авторизация не пройдена
        {
            Application->MessageBox(
                _T("Вы не можете пользоваться приложением, так как не прошли авторизацию"),
                _T("Защита приложения")
            );
        }
Таким образом можно не только отслеживать успешность/неуспешность авторизации, но и создавать свои формы для любого количества групп пользователей.

Единственное, на что хочется обратить внимание - это то, что проделывать все описанные выше операции желательно уже тогда, когда все формы по отдельности уже были созданы и отлажены, самым последним этапом. Изменение настроек проекта (в частности добавление новой формы, или изменение автосоздания формы) приведет к тому, что опять придется изменять основной файл.

В качестве примера реализаций привожу два проекта: первый - иллюстрирует чтение логина/пароля из INI, а второй - создание разных форм для каждой из групп пользователей (проекты были созданы и протестированы в Builder XE2, для создания INI-файла использовался код:
C++
1
2
3
4
5
6
7
8
9
#include <memory>
#include <IdHashMessageDigest.hpp>
 
// ...
 
    std::auto_ptr<TIniFile> ini (new TIniFile(ChangeFileExt(ParamStr(0), ".ini")));
    std::auto_ptr<TIdHashMessageDigest5> hash(new TIdHashMessageDigest5);
    ini->WriteString("users", "volvo", hash->HashStringAsHex("test", TIdTextEncoding::Default));
    ini->WriteString("users", "nata", hash->HashStringAsHex("second", TIdTextEncoding::Default));
)

Проект №1

Проект №2

P.S. Замечания/пожелания/вопросы по этой теме отсылайте мне в ЛС, я постараюсь добавить еще интересные методы авторизации.
Ответ:
Создание заставок (splash-форм) для приложения.


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


Как же создаются подобные заставки? Все очень просто, и чем-то похоже на создание формы авторизации (наверное, тем, что опять нужно лезть в файл проекта, и менять так порядок создания форм). Итак:

  1. Когда все остальные формы приложения уже созданы и работают, создаем новую форму, которая будет заставкой.
  2. Сразу же идем в свойства приложения, и убираем новую форму из списка автоматически создаваемых (Project->Options->Forms переносим форму из списка Auto-Create в список Available)
  3. Поскольку мы хотим, чтобы форма какое-то время показывалась на экране, то кладем на нее таймер, задаем максимальное время показа заставки, и по таймеру проверяем, не вышло ли еще это время:

    C++
    1
    2
    3
    4
    5
    6
    7
    8
    
    void __fastcall TSplashForm::Timer1Timer(TObject *Sender)
    {
        static int SplashTime = 3000;
        if((::GetTickCount() - FStart > SplashTime) && CanCloseSplash)
        {
            this->Close();
        }
    }
    (о назначении CanCloseSplash я расскажу чуть позже)
  4. Естественно, если не записать в FStart значение GetTickCount() при создании заставки, ничего работать не будет. Поэтому пишем обработчик создания формы:
    C++
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    void __fastcall TSplashForm::FormCreate(TObject *Sender)
    {
        FStart = ::GetTickCount();
        CanCloseSplash = false; // начальная инициализация всех полей
        Timer1->Interval = 100;
        
        // если кого-то раздражает показ заставки на самом верху,
        // следующую строку можно закомментировать
        FormStyle = fsStayOnTop; 
    }
    Ну вот практически и все, что нужно сделать с формой. Осталось только правильно ее показать.
  5. Идем в главный файл проекта (Project -> View source), и добавляем там показ формы-заставки:
    C++
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
             SplashForm = new TSplashForm(0); // создаем
             SplashForm->Show(); // и показываем заставку
     
             // теперь продолжаем инициализацию и создание главной формы приложения
             Application->Initialize();
             Application->MainFormOnTaskBar = true;
             Application->CreateForm(__classid(TMainForm), &MainForm);
             
             // сразу после того, как главная форма была создана,
             // можно закрывать заставку (если до этого время не вышло
             // и она не закрылась самостоятельно)
     
             if(SplashForm)
             {
                SplashForm->CanCloseSplash = true; // даем разрешение закрыть заставку
             }
             // и запускаем метод Run, что приведет к показу главной формы
             Application->Run();

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

Можно сделать чуть по-другому: сразу после того, как создалась главная форма, закрывать заставку. Как ни странно, для этого понадобится изменить всего лишь 2 символа в обработчике таймера:
C++
1
2
3
4
5
6
7
8
9
10
11
void __fastcall TSplashForm::Timer1Timer(TObject *Sender)
{
    static int SplashTime = 3000;
    // Меняем "И" на "ИЛИ", и теперь либо закончится время
    // показа заставки, либо CanCloseSplash станет true; заставка
    // закроется при выполнении любого из этих условий
    if((::GetTickCount() - FStart > SplashTime) || CanCloseSplash)
    {
        this->Close();
    }
}
Тестовые проекты
BCB6:


XE2:



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

Изменений в главном файле проекта почти не будет, единственное, что я поменял - это вместо метода Show вызвал самописный метод ShowSplash:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
         SplashForm = new TSplashForm(0);
         SplashForm->ShowSplash("logo.png"); // <---
 
         Application->Initialize();
         Application->MainFormOnTaskBar = true;
         Application->CreateForm(__classid(TMainForm), &MainForm);
 
         if(SplashForm)
         {
            SplashForm->CanCloseSplash = true;
         }
 
         Application->Run();
А вот реализация класса формы-заставки поменялась значительно. Во-первых, в класс формы добавился прототип того самого метода ShowSplash():
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class TSplashForm : public TForm
{
__published:    // IDE-managed Components
    TTimer *Timer1;
    void __fastcall Timer1Timer(TObject *Sender);
    void __fastcall FormCreate(TObject *Sender);
    void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
    void __fastcall FormDestroy(TObject *Sender);
private:    // User declarations
    int FStart;
    bool FCanCloseSplash;
 
public:     // User declarations
    __fastcall TSplashForm(TComponent* Owner);
    void __fastcall ShowSplash(String fn); // <---
 
    __property bool CanCloseSplash = {read = FCanCloseSplash, write = FCanCloseSplash};
};
Ну, и реализация (в XE+ использовался модуль Vcl.Imaging.pngimage.hpp)
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
void __fastcall Create_Premult_Bitmap(Graphics::TBitmap *bm)
{
    for (int y = 0; y < bm->Height; y++)
    {
        Vcl::Imaging::Pngimage::TByteArray *dst =
            (Vcl::Imaging::Pngimage::TByteArray*)bm->ScanLine[y];
        for (int x = 0; x < bm->Width; x++)
        {
            dst->data[x * 4] = dst->data[x * 4] * dst->data[x * 4 + 3] >> 8;
            dst->data[x * 4 + 1] =
                dst->data[x * 4 + 1] * dst->data[x * 4 + 3] >> 8;
            dst->data[x * 4 + 2] =
                dst->data[x * 4 + 2] * dst->data[x * 4 + 3] >> 8;
        };
    };
}
 
void __fastcall Load_Logo(Graphics::TBitmap *bm, String FileName)
{
    std::auto_ptr<TPngImage> png (new TPngImage);
    png->LoadFromFile(FileName);
    bm->PixelFormat = pf32bit;
    bm->Width = png->Width;
    bm->Height = png->Height;
    for (int y = 0; y < png->Height; y++)
    {
        Vcl::Imaging::Pngimage::TByteArray *alpha = png->AlphaScanline[y];
        TRGBLine *src = (TRGBLine*)png->Scanline[y];
        Vcl::Imaging::Pngimage::TByteArray *dst =
            (Vcl::Imaging::Pngimage::TByteArray*)bm->ScanLine[y];
        for (int x = 0; x < png->Width; x++)
        {
            dst->data[x * 4] = src->data[x].rgbtBlue;
            dst->data[x * 4 + 1] = src->data[x].rgbtGreen;
            dst->data[x * 4 + 2] = src->data[x].rgbtRed;
            dst->data[x * 4 + 3] = alpha->data[x];
        }
    }
}
 
void __fastcall TSplashForm::ShowSplash(String fn)
{
    BorderStyle = bsNone;
    Position = poDesktopCenter;
    this->FormStyle = fsStayOnTop;
 
    SIZE s1;
 
    BLENDFUNCTION blend = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
 
    TPoint p = Classes::Point(0, 0);
    ::SetWindowLong(Handle, GWL_EXSTYLE, ::GetWindowLong(Handle,
        GWL_EXSTYLE) | WS_EX_LAYERED);
 
    std::auto_ptr<Graphics::TBitmap> image (new Graphics::TBitmap);
    Load_Logo(image.get(), ExpandFileName(ExtractFilePath(ParamStr(0))) + fn);
    Create_Premult_Bitmap(image.get());
    s1.cx = image->Width;
    s1.cy = image->Height;
 
    Width = image->Width;
    Height = image->Height;
 
    std::auto_ptr<Graphics::TBitmap> layer (new Graphics::TBitmap);
    layer->PixelFormat = pf32bit;
    layer->Width = s1.cx;
    layer->Height = s1.cy;
    layer->Canvas->Brush->Color = RGB(0, 0, 0);
    layer->Canvas->FillRect(layer->Canvas->ClipRect);
 
    ::AlphaBlend(layer->Canvas->Handle, 0, 0, image->Width, image->Height,
        image->Canvas->Handle, 0, 0, image->Width, image->Height, blend);
    Create_Premult_Bitmap(layer.get());
    ::UpdateLayeredWindow(this->Handle, 0, NULL, &s1, layer->Canvas->Handle, &p,
        0, &blend, ULW_ALPHA);
 
    Show();
}
Тестовые проекты
BCB6:
собрать не получилось. Я уже говорил, что использую Portable версию Билдера, туда нельзя добавлять новые компоненты, нельзя даже просто откомпилировать pas-файл, поэтому работать с PNG не представляется возможным

XE2:




А теперь о грустном. У первого метода есть недостаток (на самом деле он есть и у второго, но поскольку картинка обычно статичная - он не так бросается в глаза). Заключается он в следующем: если при инициализации основной формы (как раз в то время, когда показывается заставка) не вызывать периодически Application->ProcessMessages(), как я делал в тестовом приложении, то форма не будет обновляться. Она просто повиснет в том состоянии, в котором была создана, и на нее не положишь ни ProgressBar, ни Label, в которые можно вывести какую-то информацию о том, на каком этапе находится сейчас процесс загрузки приложения.

Чтобы этого избежать можно:
  1. Вынести все действия по инициализации в отдельный поток.
  2. Создать и показать заставку
  3. Запустить поток инициализации
  4. По завершению работы потока закрывать заставку

Убиваем двух зайцев: во-первых, ОС не считает заставку "зависшей" формой, во-вторых, пользователь тоже так не считает, поскольку видит, что информация на ней меняется. Приведу, кому интересно, пример приложения, реализующего вышеописанную схему, с потоком. Запустите и посмотрите (для того, чтобы проверить - добавил искусственных задержек в поток)

Тестовые проекты
BCB6:


XE2:




Ну вот и все, пожалуй, о Splash-формах.


P.S. Замечания/пожелания/вопросы приветствуются, обращайтесь в ЛС, если будет что-то интересное - добавлю в пост.
Вопрос: Необработанное исключение типа "System.Exception"

На форме есть datagridview и menustrip. Код компилируется без ошибок, но при попытке сохранить файл ругается на необработанное исключение типа "System.Exception". Помогите исправить ошибку пожалуйста, сам решить не смог. Код писался в Visual Studio 2013.



Код 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
private void SaveFile (object sender)// сохранения файла  
                {
                    Microsoft.Office.Interop.Excel.Application Exl = new Microsoft.Office.Interop.Excel.Application();
                    Microsoft.Office.Interop.Excel.Workbook wb;
 
                    XlReferenceStyle RefStyle = Exl.ReferenceStyle;
                    Exl.Visible = true;
 
                    String TemplatePath = System.Windows.Forms.Application.StartupPath + @""\Шаблон.xls"; ;
                    try
                    {
                        wb = Exl.Workbooks.Add(TemplatePath);
                    }
                    catch (System.Exception ex)
                    {
                        throw new Exception("Не удалось загрузить шаблон для экспорта " + TemplatePath + "\n" + ex.Message);
                    }
                    Worksheet ws = wb.Worksheets.get_Item(1) as Worksheet;
 
                    for (int j = 0; j < dataGridView1.Columns.Count; ++j)
                    {
                        (ws.Cells[1, j + 1] as Range).Value2 = dataGridView1.Columns[j].HeaderText;
                        for (int i = 0; i < dataGridView1.Rows.Count; ++i)
                        {
                            object Val = dataGridView1.Rows[i].Cells[j].Value;
                            if (Val != null)
                                (ws.Cells[i + 2, j + 1] as Range).Value2 = Val.ToString();
                        }
                    }
                    ws.Columns.EntireColumn.AutoFit();
                    Exl.ReferenceStyle = RefStyle;
                    ReleaseExcel(Exl as Object);
                }
Ответ: Даценд, файл на месте. Вот полный текст ошибки:

Необработанное исключение типа "System.Exception" в WindowsFormsApplication1.exe

Дополнительные сведения: Не удалось загрузить шаблон для экспорта C:\Users\Roma\Desktop\Лабораторные работы\Курсовая работа\WindowsFormsApplication1\WindowsFormsApplication1\bin\DebugC:\Users\Roma\Desktop\Лабораторные работы\Курсовая работа\WindowsFormsApplication1\WindowsFormsApplication1\Шаблон.xlsx

Приложению Microsoft Excel не удается получить доступ к файлу "C:\Users\Roma\Desktop\Лабораторные работы\Курсовая работа\WindowsFormsApplication1\WindowsFormsApplication1\bin\DebugC:\Users\Roma\Desktop\Лабораторные работы\Курсовая работа\WindowsFormsApplication1\WindowsFormsApplication1\Шаблон.xlsx". Это может быть вызвано одной из следующих причин.



• Указан несуществующий файл или путь.

• Файл используется другой программой.

• Имя книги, которую вы пытаетесь сохранить, совпадает с именем другой книги, открытой в данный момент.

Добавлено через 3 минуты
Всем спасибо за помощь, ошибку эту я исправил. Но возникла другая проблема. При сохранении таким способом ПОСЛЕДНЯЯ! ячейка заполненная мной в DataGridView не записывается в файл (будь то ячейка в середине таблицы или в конце).
Вопрос: Windows-приложение "Формирование реестра заказов "

Помогите пожалуйста, не совсем понимаю как реализовать данное задание

Создать Windows-приложение "Формирование реестра заказов ".
Предусмотреть:
1. Создание входных файлов:
Справочник услуг (Код услуги, Наименование услуги, Стоимость услуги);
Клиенты (Код клиента, Наименование клиента, Адрес, Теле-фон).
2. На основе данных входных файлов и заданного в форме Кода клиента, Кода услуги и Стоимости услуги получение выходного файла:
Заказы (Номер заказа, Дата заказа, Код клиента, Код услуги, Стоимость услуги).
3. Вывод Общей стоимости заказа по заданному Номеру заказа.
4. Создание меню для выполнения всех указанных в задании пунктов.
Ответ: Методичку смотрел? Ведь, наверняка, там пример имеется
И с указанием в каком формате иметь данные и в каком формате выходные данные. Скорей всего в простых текстовых файлах.
В справке есть нормальные примеры работы с файлами
В данном примере инструкция Print # используется для записи данных в файл.

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Open "TESTFILE" For Output As #1    ' Открывает файл для записи.
Print #1, "Пример"  ' Печатает текст в файл.
Print #1,   ' Печатает пустую строку в файл.
Print #1, "Зона 1"; Tab ; "Зона 2"  ' Печатает в двух зонах печати.
Print #1, "Пример" ; " " ; "всем"   ' Строки разделяются пробелом.
Print #1, Spc(5) ; "5 пробелов" ' Печатает пять пробелов.
Print #1, Tab(10) ; "Привет"    ' Печатает слово в столбце 10.
 
' Присваивает значения типа Boolean, Date, Null и Error.
Dim MyBool, MyDate, MyNull, MyError
MyBool = False : MyDate = #February 12, 1969# : MyNull = Null
MyError = CVErr(32767)
' Вместо слов True, False, Null и Error записываются слова, 
' соответствующие им в текущем языке. Текстовые константы даты 
' записываются в кратком системном формате даты.
Print #1, MyBool ; " - логическое значение"
Print #1, MyDate ; " - дата"
 
Print #1, MyNull ; " - значение Null"
Print #1, MyError ; " - значение типа Error"
Close #1    ' Закрывает файл.
В данном примере инструкция Input # используется для чтения данных из файла в две переменные. Предположим, что текстовый файл TESTFILE существует и содержит несколько строк текста, записанных с помощью инструкции Write #, т.е. каждая строка содержит заключенную в кавычки строку и отделенное от нее запятой число, например ("Привет", 234).

Visual Basic
1
2
3
4
5
6
7
Dim MyString, MyNumber
Open "TESTFILE" For Input As #1 ' Открывает файл для чтения.
Do While Not EOF(1) ' Цикл до конца файла.
    Input #1, MyString, MyNumber    ' Читает данные в две переменные.
    Debug.Print MyString, MyNumber  ' Выводит данные в окно отладки.
Loop
Close #1    ' Закрывает файл.