Последние записи
- Модуль числа |a| без условных операций на CMD
- Как копировать текст из блока в буфер обмена?
- Получение ProductKey установленной Windows
- Как парсить https сайт ?
- Смена регистра строки текста на BAT (CMD)
- Вывод разноцветного текста на BAT (CMD)
- Узнать дату окончания сертификата
- Как создать полноценный сайт на Open Server
- Получить температуру процессора на bat-файлах
- Динамические массивы в Lazarus / Delphi — индексация элементов
Интенсив по Python: Работа с API и фреймворками 24-26 ИЮНЯ 2022. Знаете Python, но хотите расширить свои навыки?
Slurm подготовили для вас особенный продукт! Оставить заявку по ссылке - https://slurm.club/3MeqNEk
Online-курс Java с оплатой после трудоустройства. Каждый выпускник получает предложение о работе
И зарплату на 30% выше ожидаемой, подробнее на сайте академии, ссылка - ttps://clck.ru/fCrQw
24th
Фев
Как разделить строку на два числовых массива?
Подскажите как можно реализовать: вот есть у меня текстовый файл для проекта, в нем две колонки данных и делитель 4 пробела, как мне сделать из него 2 массива данных. один массив — одна колонка данных, второй — вторая, а потом по ним построить график. Зараннее благодарю! (читать всё…)
24th
Как скрыть какой либо объект на javascript?
как скрыть какой либо объект на javascript?
я знаю как делать это при помощи библиотеки jquery но хочу научится и на простом javascript. (читать всё…)
24th
Как получить список всех открытых окон?
Как получить список всех открытых окон? Запишу допустим я список этих окон в листбокс, как потом узнать у выбранного окна из списка его размеры? (читать всё…)
24th
Назначить событие на OnClick для TMenuItem
Подскажите какой параметр надо передавать или может как по-другому для динамически созданного TMenuiIem создать событие OnClick, чтобы можно было его в процедуре распознать(какой именно вызвал).
Баламут:
Это делается примерно так.
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus;
type
TForm1 = class(TForm)
PopupMenu1: TPopupMenu;
N1: TMenuItem;
procedure PopupMenu1Change(Sender: TObject; Source: TMenuItem;
Rebuild: Boolean);
private
procedure ItemClick(Sender: TObject);
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.ItemClick(Sender: TObject);
begin
ShowMessage(‘ПРЕВЕД!’);
end;
procedure TForm1.PopupMenu1Change(Sender: TObject; Source: TMenuItem;
Rebuild: Boolean);
begin
Popupmenu1.Items[0].OnClick := ItemClick;
end;
23rd
Фев
Как отправить пост-запрос в дельфи на сервер, и получить от сервера ответ?
DeDoK:
Отправляет он и получается просто
s : TstringList;
str : string;
begin
s:=TStringList.Create;
s.Add(‘login=’);
s.Add(‘pass=’);
// вобщем добавляем свои параметры
str:=idHttp1.Post(‘http://’,s);
//в str будет ответ
end;Syhi-подсветка кода
23rd
Как узнать на какой UIN пришло сообщение TICQClient?
У меня такой вопросик: создаются TICQClient программно. Допустим создали мы три учетные записи и подключились к сети всеми тремя UINами. Как определить к какой из учетных записей пришло сообщение, чтобы его в дальнейшем обработать?
Пепел Феникса:
в событии Sender это обьект вызвавший событие.
23rd
Копировать содержиое listbox
Last:
Здравствуйте, есть два listbox’а, надо скопировать элементы из одного в другой. Пишу на Си:
разобрался, код выглядит так:
switch (whi)
{
case BN_CLICKED:
{
int i = 0, n;
n = SendMessage(GetDlgItem(hwnd, IDL_LIST_FILENAME) ,LB_GETCOUNT,0,0);
for (i = 0; i < n; i++)
{
LPTSTR *String = (LPTSTR*)malloc(1024*sizeof(TCHAR));
SendMessage(GetDlgItem(hwnd, IDL_LIST_FILENAME), LB_GETTEXT, i, (LPARAM)String);
SendMessage(GetDlgItem(hwnd, IDL_LIST_SEL_FILENAME), LB_ADDSTRING, 0, (LPARAM)String);
free(String);
}
}
}
return 0;Syhi-подсветка кода
23rd
WMI. Wладение Mагической Iнформацией. Часть 2
Здравствуйте, уважаемые читатели! Помните меня? А статью про WMI, где я на двух языках показывал как просто получить власть над Windows посредством… Ктулху? Не-е-е. Читаем дальше? Однозначно, сегодня мы продолжим наши изыскания…
Продолжение. Начало смотрите в предыдущем номере журнала…
Виталий Белик
by Stilet www.programmersforum.ru
Ну, да ладно. Мы же пойдем ровным путем, дающим краткое, но четкое представление о том, как будет работать система. Заранее раскрывая карты, скажу, что с Делфийском коде обращение к записям и полям таблицы будет похоже на обращение к ячейкам массива.
Двумерного разумеется. На С++
TWMIRecord *r=0;
// Инициируем итератор для списка
list<twmirecord>::iterator k;
// Пройдемся циклом по списку пока не дойдем
// до указанной по номеру записи
for(k=RecList.begin();(k!=RecList.end())&&(i>0);k++,i—);
// Если записть такая нойдена, в том смысле
// что индекс запрошенной записи
// не вылезает за пределы списка
// то вернем объект из списка
if(k!=RecList.end()&&i>=0){
r=&*k;
}
return r;
};Syhi-подсветка кода
Здесь единственный бок – я не знаю, как проверить выход за пределы списка указанного номера запрошенной записи, и так же не знаю другого способа получить по номеру из списка без прохода циклом. Поэтому я решил просто написать проход циклом по списку, пока не конец, или пока нужный номер записи в списке не достигнут. В принципе это работает, так что пусть так и остается.
Ладушки. Пора приступать к описанию второго класса, класса отвечающего за обработку записи TWMIRecord (на Делфи):
private
// Список полей и их значений
FFields:TStringList;
// Процедура получения данных из полей записи
Procedure Enum(Obj:OleVariant);
Constructor Create;
Destructor Free;
function GetItem(v: Variant): String;
public
Path:String;
// Функция возвращающая число полей
Function HighRecordIndex:Integer;
// Функция, возвращающая имя i-того поля
Function FieldName(i:integer):String;
// Свойство получающее значение определенного поля
Property Item[v:Variant]:String read GetItem; default;
end;Syhi-подсветка кода
Здесь особое внимание должно быть уделено процедуре Enum(), которая, приняв объект-запись от энумератора записей, прокатится по ее полям, выделив ее значения в свой список, и свойство Item, объявленное по умолчанию. Оно может принимать как строку – при этом получить значение по имени поля, так и число, чтоб получить значение из поля по определенному номеру. Это дает серьезную мобильность, можно в цикле пройтись по полям, а можно просто получить значение по имени поля (на С++):
// Имя поля
wstring Name;
// Значение поля, переведенное в строку
wstring Value;
};
class TWMIRecord
{
private:
// Свойство, принимающее значение поля
VARIANT Prop;
// Обьект-записи полученный от провайдера
IWbemClassObject *Obj;
wstring FString;
// Список полей и их значений
list<sfield> FFields;
// Количество полей
int CountList;
public:
TWMIRecord(IWbemClassObject *AObj);
~TWMIRecord(void);
// Метод, получающий поле по имени
sField Field(wstring AName);
// Метод получающий поле по номеру
sField Field(int iName);
// Функция, получающая верхний индекс в списке полей
int high();
};Syhi-подсветка кода
Кто-то скажет: «А зачем Field(wstring AName) возвращает структуру, достаточно ведь вернуть значение?». Верно, но вдруг захочется пополнить структуру еще какой-нибудь характеристикой поля, например, типом, так что пусть этот метод возвращает всю структуру – ничего пагубного в этом нет. Ок. Реализуем этот класс (на Делфи):
constructor TWMIRecord.Create;
begin
// Создается класс списка полей и их значения
FFields:=TStringList.Create;
// Здесь я не предполагал хранить ничегокроме имя и значения поля
// так что TString’a вполне хватит
end;
// Метод проходя по полям
procedure TWMIRecord.Enum(Obj: OleVariant);
var PropEnum:IEnumVariant; i:Cardinal; s:string; d:double;
begin
// Приготовим список для внесения в него данных
FFields.Clear;
// Инициализируем энумератор
PropEnum:=IEnumVariant(IUnknown(Obj.Properties_._NewEnum)); //Поля
// и начнем по нему лазить, пока он выбирает записи
while (PropEnum.Next(1, Obj, i) = S_OK) do begin
try
// Здесь я прикрутил распознавание типа даты
// если поле содержит дату, то привести ее в
// понятный человеку вид
if obj.CIMType=$00000065 then begin
s:=Obj.Value;
s:=copy(s,7,2)+‘.’+copy(s,5,2)+‘.’+copy(s,1,4);
end else
// если же это не дата, то пусть сама программа приводит
// значение к строке. в противном случае в строку
// должно писаться значение [NULL], если такое поле пусто
if VarIsNull(Obj.Value) then s:=WMIValueNull else s:=Obj.Value;
FFields.Values[Obj.Name]:=s;
except
end;
end;
end;
function TWMIRecord.FieldName(i: integer): String;
begin Result:=»;
// если номер попадает в список полей, вернем имя поля
// по его номеру
if (i>=0)and(i<FFields.Count) then
Result:=FFields.Names[i];
end;
destructor TWMIRecord.Free;
begin
// Освободим список, уберем мусор
FFields.Free;FFields:=nil;
end;
function TWMIRecord.GetItem(v: Variant): String;
begin
Result:=»;
// Если мы хотим получить значение по номеру поля
// нужно проверить, не выходит ли указанный индекс
// за пределы списка полей
if VarIsOrdinal(v)and(v>=0)and(v<FFields.Count) then
// И если не выходит — вернуть это поле
Result:=FFields.Values[FFields.Names[v]];
// если же мы хотим получить значение поля по имени
if VarIsStr(v) then
// мы просто передаем имя, и если
// поле с таким именен есть возвращается его значение
Result:=FFields.Values[v];
// иначе вернется пустая строка
end;
function TWMIRecord.HighRecordIndex: Integer;
begin
// Последний индекс в списке полей
Result:=FFields.Count-1;
end;Syhi-подсветка кода
Что тут добавить еще? Энумератором получаем поля и их значения, раскладывая в «массив». И даем возможность выбирать из этого массива в самой программе, любым способом, по индексу или по имени. И еще константа const WMIValueNull='[NULL]’. На С++:
{
Obj=AObj;
HRESULT hres;
BSTR pstrName;
VARIANT pVal;
CIMTYPE pvtType;
sField field;
// Начинаем перечисление
hres=Obj->BeginEnumeration(0);
CountList=0;
// Если это возможно конечно, проходимся циклом
// пока не нарвемся на ошибку, или пока энумератор не
// выберет все данные
while(!FAILED(hres)&&(hres!=WBEM_S_NO_MORE_DATA)){
// Получим очередное "следующее" поле
hres=Obj->Next(0,&pstrName,&pVal,&pvtType,0);
// Если оно удачно получено
if(!FAILED(hres)&&(hres!=WBEM_S_NO_MORE_DATA)){
field.Name.clear();
// Запишем его имя
field.Name=wstring(_bstr_t(pstrName,false));
// Если его значение не пусто
if(pVal.vt!=VT_NULL){
field.Value.clear();
// получим его, преобразовав в строку в зависимости
// от типа
switch(pvtType){
case wbemCimtypeBoolean:
field.Value=(pVal.boolVal)?L"TRUE":L"FALSE";
break;
case wbemCimtypeString:
field.Value=wstring(_bstr_t(pVal.bstrVal,false));
break;
case wbemCimtypeSint32:
int i=pVal.intVal;
char c[30]="";
itoa(i,c,10);
for(int i=0;i<10&&c[i]!=0;i++){field.Value+=c[i];}
break;
}
}
// и внеся новое поле в наш список
FFields.push_back(field);
// увеличим счетчик количества полей
CountList++;
}
}
}
int TWMIRecord::high()
{
// Вернем верхний индекс списка полей
return CountList-1;
}
TWMIRecord::~TWMIRecord(void)
{
// Освободим список
FFields.clear();
}
sField TWMIRecord::Field(wstring AName){
FString=L"";
sField res={L"",L""};
// Приготовим итератор для прохода по списку
list<sfield>::iterator i=FFields.begin();
// пока не конец списка
for(;i!=FFields.end();i++){
// получим очередной элемент
sField ws=*i;
// проверим не совпадает ли имя поля
// полученного элемента с указанным нами
if(ws.Name==AName){
// Если совпадает — выйдем из цикла
res=*i;
break;
}
}
return res;
};
sField TWMIRecord::Field(int iName){
FString=L"";
sField res;
// Приготовим итератор для прохода по списку
list<sfield>::iterator i;
// пока не конец списка или не достигнут указанный индекс поля
for(i=FFields.begin();(i!=FFields.end())&&(iName>=0);i++,iName—);
// Если список полей весь пройден а индекс поля еще не достигнут
// вернем пустые строки.
if(i!=FFields.end() && iName>=0){ res.Name=L"";res.Value=L"";}
// Иначе вернем данные из списка
else {res=*i;}
return res;
};Syhi-подсветка кода
Опять-таки, итерации по списку – в Делфи, дяди из Борланда дали возможность обращаться к элементам списка как к массиву, как сделано в STL я не знаю, поэтому банально – прошелся циклом по list’y.
Так… Вроде ничего не забыли описать? Если нет, то пора попробовать эту махину в действии.
Starting Line
Начнем, пожалуй, с Делфи. Создадим проект с формой, на него кинем StringGrid, и в обработчике создания формы OnCreate напишем такой код (на Делфи):
var w:TWMI;i,j:integer; wr:TWMIRecord;
begin
// Создадим обьект WMI
w:=TWMI.Create(nil);
// Выкатим ему запрос
w.SQL:= ‘SELECT caption, CommandLine FROM Win32_Process’;
with StringGrid1 do begin
// Развернем Грид на нужно е количество записей
RowCount:=w.HighObject+1;
FixedCols:=0;
// В цикле пройдясь по записям
for i:=0 to w.HighObject do begin
wr:=w[i];
if ColCount<(wr.HighRecordIndex+1) then ColCount:=(wr.HighRecordIndex+1);
// впишем значения полей в таблицу
for j:=0 to wr.HighRecordIndex do begin
Cells[j,i]:=wr[j];
end;
end;
end;
w.Free;
end;Syhi-подсветка кода
Перед этим не забудем создать в проекте Unit (назовем его Unit2), и вложить в него код классов, не забыв в нем указать необходимые модули для работы механизма в описанный классах uses Classes,contnrs,variants,ActiveX,Comobj; Не забыв указать в разделе uses модуля формы этот самый Unit2.
Теперь код обработчика на форме связан с модулем, где описаны классы.
Если все проделано правильно после жмака по F9 на экран выкатится форма со списком процессов (см. рисунок 1):
Рис. 1. Работа программы написанной на Делфи
Ну вот. Запрос SELECT caption, CommandLine FROM Win32_Process получил набор с заголовками запущенных в целевой системе процессов, и путями к файлам этих процессов. Администратору сразу видно, что запущено у пользователя, не нужно идти к нему, или использовать платные средства удаленного администрирования. Увы, не все они могут показать такую информацию, а иногда это важно для понимания состояния системы.
А теперь тоже самое но на С++. Лукаво не мудрствуя, сделаем это в консоли, это попроще будет:
#include "TWMI.h"
#include <locale>
#include <iostream>
int _tmain(int argc, _TCHAR* argv[])
{
// Включим русский язык для консоли
setlocale(LC_ALL,"russian");
// Создадим класс WMI
TWMI *wmi=new TWMI();
// Скормим ему запрос
if(wmi->SetQuery("SELECT caption FROM Win32_Process")){
// Если запрос удачно обработал
printf("Получили данные\n");
int i=0;
// В цикле пройдемся по записям,
for(TWMIRecord *r=wmi->Item(i);r;i++,r=wmi->Item(i)){
// И выведем значение поля
wcout<<r->Field(L"Caption").Value<<‘\n‘;
}
} else {printf("Неудача");}
// после чего уберем мусор
delete wmi;
getchar();
return 0;
}Syhi-подсветка кода
Здесь тоже самое, разве что я изменил запрос. Попросил только заголовки процессов. В консоли красиво не выведешь. Здесь же применен метод получения поля по его имени, но с таким же успехом его можно заменить на:
sField f=r->Field(i);
wcout<<f.Name<<‘=’<<f.Value<<‘\n‘;
} wcout<<‘\n‘;Syhi-подсветка кода
Где в цикле будет вестись проход по всем полям по их номеру. Запустим и посмотрим, что же получилось (см. рисунки 2, 3):
Рис. 2. Получение по имени поля
Рис. 3. Получение нескольких полей
Запрос на рисунке 2 показывает, что все хорошо прошло. Объект получил от провайдера WMI информацию, и программа вывела ее на экран. На втором же рисунке показана возможность показа всех полей, одна запись тут разделена пустой строкой. Вообще я в запросе указал два поля CommandLine, но провайдер предоставляет кроме этого еще несколько, судя по всему стандартных полей, характеризующих тип самого запроса. Например, свойство __PROPERTY_COUNT=2 говорит о том, что мы запросили два поля, между прочим, им можно пользоваться, чтоб узнать количество полей. А __CLASS=Win32_Process говорит о том, какое «представление» использовалось. Мы хотели получить список процессов – вот и получили, соответственно и класс Win32_Process. Ну и, конечно же, в конце данные о тех самых наших полях, которые мы запрашивали, Caption и CommandLine. Все работает замечательно.
Теперь можно самостоятельно написать свою «тулзу» для удаленного администрирования. Учитывая, что классов в WMI много, можно много чего узнать о компьютерах в сети. Например, можно узнать, что за пользователи описаны в компьютере, выкатив запрос SELECT * FROM Win32_Account (см. рисунок 4):
Рис. 4. Информация о пользователях на целевой машине
Или предположим звонит юзер:
-у меня материнка с ума сошла, дайте дрова!
-какая у вас материнка?
-пластиковая, из магазина…
Да-да. Это не анекдот. Юзеры, иногда в силу своей компьютерной неграмотности, такое откалывают, что Задорнов «плякаль». А, запросив SELECT * FROM Win32_BaseBoard у виндоуса того пользователя можно увидеть, что у него (см. рисунок 5):
Рис. 5. Параметры материнской платы
Оказывается Асус. О! И даже серийник есть. Ну, теперь просто запросить на сайте производителя дровишки для P5GZ-MX и удаленно RAdmin’ом например проинсталлировать. Кто-то скажет: «Так, а чего самим РАдмином или типа него не посмотреть денить в свойствах?» Где? Все знают, где информация такая лежит? Ану-ка, партизаны: «шнель шпрехен… ». Я лично не знаю, где можно посмотреть такие подробности. А тут раз – и все как на ладони. А тем паче, своя Наташка… ))))
Post Scriptum
Ну вот. Собственно, на этом можно поставить точку. А можно и троеточие, ибо WMI помимо получения информации позволяет управлять компьютером. Опять-таки теми же запросами. «Тушить процессы» или выключать компьютер удаленно.
Например, если вызвать метод Terminate класса, полученного по запросу на Win32_Process, то можно потушить все процессы из запроса. Порывшись в MSDN, можно даже найти пример [2]. Если ссылку еще не завалили, посмотрите, как это делается: Запросом получается набор объектов, у которых вызывается метод Terminate, и они тушатся.
В общем, все это очень обнадеживает, и, если системный администратор владеет этим каратэ – цены ему нет. Домен свой он будет держать атланту подобно. Так что рекомендую вляпаться в эти микрософтовские катакомбы – не пожалеете.
The Чтиво
- Ресурс вики http://ru.wikipedia.org/wiki/WMI
- MSDN http://msdn.microsoft.com/en-us/library/aa393907%28VS.85%29.aspx
Статья из девятого выпуска журнала «ПРОграммист».
Обсудить на форуме — WMI. Wладение Mагической Iнформацией. Часть 2
23rd
Быстрое написание программ на WinAPI
Все программисты делятся на две группы – oldschool и новую волну. Сыны старой школы помнят историю о 640 килобайтах, помнят о тысяче игр на одной дискете… Новая волна, чаще всего, даже не знает устройство компьютера, но так же считается – программистами. Использование IDE изменило представление о программистах. Посмотрим, что же может дать отказ от визуального программирования. В этой статье я опишу один из способов быстрого написания приложений с использованием функций WinAPI.
Алексей Шишкин
by Alex Cones http://flsoft.ru
Вступление или «Кому это нужно?»
Вы можете задаться вопросом, зачем же насиловать свой мозг, если давным-давно изобретена VCL, MFC и прочие прелести визуального программирования? Для ответа на этот вопрос давайте посмотрим на плюсы и минусы визуального и низкоуровневого* программирования.
Итак, рассмотрим плюсы визуального программирования:
- быстрое написание программ (достаточно накидать кнопок на форму и написать их процедуры);
- удобство использования (это удобнее, чем описывать каждый шаг на низком уровне, не нужно заботиться о памяти).
И минусы:
- огромный размер приложений — «пустое» приложение на Delphi «весит» ~300 кб;
- из-за огромного количества надстроек быстродействием приходится пренебречь, особенно в плане графики на Canvas.
И в противоположность, рассмотрим плюсы низкоуровневого программирования на WinAPI:
- малый размер конечных файлов (согласитесь, что между 30 кб и 300 кб есть большая разница);
- быстродействие на достаточно высоком уровне (быстрее получится только, если писать целиком на ассемблере – то еще удовольствие).
И минусы:
- нет визуализации (труднее представить, что создать, что уничтожить, что где писать);
- для создания обычного окна потребуется примерно 50 строк кода (создать и зарегистрировать само приложение, создать окно, заботиться о всех параметрах);
- необходимо помнить о необходимости следить за использованием памяти — освобождением, взятием. Здесь обычным *.Free не обойдешься.
Но, если мы представим, что избавились о минусах программирования на WinAPI, чаша весов склонится в сторону низкоуровневого программирования. Так как же нам от них избавиться? Итак, взглянем в сторону фреймворков, которые это позволяют. За всю мою практику программирования на Delphi сталкивался с таким только единожды** – APIx 2 (Visual WinAPI). Но данное средство разработки не предполагает активное использование графики, только создание окон и кнопок. Поэтому я решил создать такую библиотеку, которая позволит не только быстро создавать окна, но и активно использовать графику.
Не хвастаясь особо, сообщу, что мне это удалось. И через три недели разработки GRAY FUR был готов.
WTF… или что это даст?
Mon ami, это же элементарно: не нужно заботиться о расходе и приходе памяти, размышлениям о бренности окон. Да, мы по прежнему не имеем дела с визуальностью, но, согласитесь, что намного удобнее вызвать одну процедуру, чем записывать пару десятков с многочисленными параметрами. Так, например отрисовать текстуру на экране можно так:
Loc : HDC;
TNum : Integer;
Begin
Loc := CreateCompatibleDC(DC);
SelectObject(Loc, Bitmap);
BitBlt(DC,
X, Y,
Width,
Height,
Loc,
0, 0,
SRCCOPY);
DeleteDC(Loc);
End;Syhi-подсветка кода
А можно и так:
Причем, если мы не подумаем о том, как создать двойную буферизацию в первом случае изображение будет мерцать при отрисовке. Во втором случае все это уже встроено в систему.
Panic button
Рассмотрим написание Panic button с использованием нашей системы. Для того, кто еще не читал моей статьи о создании Panic Button на WinAPI [1] поясню, что эта кнопка на экране будет сворачивать все окна по нажатию на нее.
Итак, скачаем FrameWork и посмотрим, как же это делается. По привычке, я буду делать это на Lazarus, но вы так же можете использовать Delphi, используя пакет для разработки под Delphi.
Для начала создадим то, что кнопка должна делать:
Begin
Keybd_event(VK_LWIN,0,0,0); // Эмулируем нажатие клавиши Win
Keybd_event(VK_D ,0,0,0); // Эмулируем нажатие клавиши D
Keybd_event(VK_D ,0,KEYEVENTF_KEYUP,0); // Отпустим D — все окна свернутся
Keybd_event(VK_LWIN,0,KEYEVENTF_KEYUP,0); // Отпустим Win.
End;Syhi-подсветка кода
Так же сделаем процедуру закрытия приложения:
Begin
DestroyTimer(ID); // Удалим таймер, созданием которого мы еще займемся
DestroyApplication; // Уничтожим приложение
End;Syhi-подсветка кода
И для полного счастья сделаем так, чтобы кнопка всегда была наверху:
Begin
SetformOnTop(Form1, TRUE); // Установим её всегда сверху.
End;Syhi-подсветка кода
Да, и еще создадим функцию для вычисления вертикальной позиции:
Var
R : Rect;
H : Handle;
W : Integer;
PH : Integer;
Begin
W := GetSystemMetrics(SM_CYSCREEN); // Получаем вертикальное разрешение
ZeroMemory(@R, SizeOf(R));
H := FindWindow(‘Shell_TrayWnd’, Nil); // Найдем окно панели задач
GetWindowRect(H, R); // Его размеры
PH := R.Bottom — R.Top; // Вычислим высоту
Result := W — PH — Form1.Height; // И получим искомое
End;Syhi-подсветка кода
Рассмотрим само тело программы:
{$mode delphi}{$H+} // Директивы для Lazarus
Uses
Windows, // Подключим Windows
Scow; // Подключим модуль-связку проекта
Var
Form1 : TForm; // Наше главное окно. Тип описан в Scow
ID : Integer; // ID таймера
// Здесь находятся процедуры, описанные выше
begin
CreateApplication; // Создаем приложение
SetApplicationReaction1(HN_LBUTTONDOWN, HideAll); // Назначим событие по левому клику
SetApplicationReaction1(HN_RBUTTONDOWN, KillMe); // Назначим событие по правому клику
CreateForm(Form1, FALSE); // Создадим форму FALSE — не показывать на панели задач
ShowForm(Form1, TRUE); // Покажем ее на экране
ResizeForm(Form1, 64, 64); // Назначим размеры
MoveForm(Form1, 0, CalculateYp); // И положение
LoadTexture(Form1, ‘Button.bmp’, ‘Button’); // Загрузим текстуру в хранилище****
Draw(Form1, ‘Button’, 0, 0, FALSE); // Нарисуем текстуру на буфере
BufferDraw(Form1); // И выведем его на экран
ID := CreateTimer(1000, OnTop); // Создадим таймер для вызова процедуры OnTop
CollectMessages; // И организуем цикл сбора сообщений для корректной работы приложения
end. // That’s all, folks!Syhi-подсветка кода
Да, и это все, как и говорится в последней строке программы. Попробуйте поискать многочисленные работы с памятью и прочими непристойностями — их просто нет. Таким образом, мы избавились от главного минуса программ на WinAPI – скорости и сложности написания. И получили плюсы – размер проекта на Delphi всего ~20 кБ по сравнению с ~300 и 39 кБ в Lazarus по сравнению с ~900 кБ. Так же не пострадало и быстродействие – прямые работы с памятью в операциях с графикой и прямой вызов WinAPI функций в проекте.
Вместо заключения
Итак, использование фреймворка дало свои плюсы. Быстрота написания (на это у меня ушло не более 3-х минут), малый размер и быстродействие – все это в одном флаконе. Так же, так как практически все функции имеют понятные названия и параметры то его можно запросто использовать для обучения основам управления программой на WinAPI. В общем, я надеюсь, что он, повторяя путь развития паскаля, перейдет в массы.
Ссылки
- Алексей Шишкин. WinAPI графика. Panic button. – ПРОграммист, Клуб ПРОграммистов, 2010, №8, с.24
- Скачать проект GRAY FUR http://squary.ru/wiki/index.php
Статья из девятого выпуска журнала «ПРОграммист».
23rd
О правильном составлении ТЗ. Часть 2
Прежде всего, хочу извиниться перед читателями, за то, что продолжение первой статьи запоздало, простуда подкралась незаметно. Ну, вот я готова представить вашему вниманию следующую часть рассказа о правильном составлении ТЗ. В прошлой статье я постаралась ответить на вопросы: что такое ТЗ, зачем оно нам необходимо и кто должен его писать. Также постаралась раскрыть возможные последствия отсутствия ТЗ и его неграмотного написания. В этой части я постараюсь рассказать, что нужно и как нужно писать в первых четырех частях ТЗ.
Дарья Устюгова
by Sparky ustyugova90@mail.ru
Введение
В прошлой части материала я привела содержание ТЗ, сложившееся у меня на основе написанных мною ТЗ и прочтенных книгах. Для того, чтобы не заставлять вас искать содержание в прошлом номере и сохранить целостность повествования, приведу его еще раз.
Прежде, чем начать разбор того, что же нам писать в ТЗ, хочу затронуть еще один формальный и очень важный момент: оформление ТЗ. Касаться моментов оформления текста ТЗ я не буду, все описано в ГОСТ 19.106-78 Требования к программным документам, выполненным печатным способом. Что же я хочу обсудить? Я хочу заострить ваше внимание на титульном листе. Что же в нем такого важного и ценного? Именно на нем ставятся подписи разработчика и заказчика. Собственно только после того когда мы и заказчик поставим их, можно приступать к работе. До этого момента ТЗ не имеет никакого юридического веса. Здесь необходимо вспомнить о плюсе ТЗ: ТЗ документ официальный. И именно на его основе будет решаться, выполнили ли мы все необходимые работы. Как оформить титульный лист описано в ГОСТ 19.104-78 Основные надписи. Теперь мы разберемся с каждым пунктом содержания по отдельности.
Содержание ТЗ:
1. Введение
1.1. Наименование программы
1.2. Краткая характеристика области применения программы
1.3. Сроки исполнения работ
2. Основания для разработки
2.1. Заказчик
2.2. Исполнитель
2.3. Основание для разработки
3. Назначение разработки
3.1. Общая концепция системы
3.2. Описание функциональности системы
4. Требования к программе
4.1. Требования к информационным структурам и методам решения
4.2. Требования к функциональным характеристикам
4.3. Требования к надежности
4.3.1. Требования к обеспечению надежного функционирования системы
4.3.2. Типы отказов при работе с системой
4.3.3. Время восстановления после отказа
4.3.4. Допустимые потери данных при отказе
4.3.5. Важная информация, которая должна быть защищена от разрушения
4.3.6. Отказы из-за некорректных действий пользователей системы
4.4. Условия эксплуатации
4.4.1. Климатические условия эксплуатации
4.4.2. Требования к квалификации и численности персонала
4.5. Требования к составу и параметрам технических средств
4.5.1. Требования к серверному аппаратному обеспечению
4.5.2. Требования к клиентскому аппаратному обеспечению
4.5.3. Требования к сетевому аппаратному обеспечению
4.6. Требования к информационной и программной совместимости
4.6.1. Требования к исходным кодам и языкам программирования
4.6.2. Требования к программным средствам, используемым программой
4.6.3. Требования к защите информации и программы
4.7. Маркировка и упаковка
4.8. Транспортировка и хранение
4.9. Специальные требования
5. Требования к программной документации
6. Технико-экономические показатели
7. Стадии и этапы разработки
7.1. Стадии разработки
7.2. Этапы разработки
7.3. Содержание работ по этапам
8. Порядок контроля и приемки
8.1. Виды испытаний
8.2. Общие требования к приемке работ
9. Порядок корректировки Технического задания
Наименование программы
В данном пункте все довольно просто и банально… Мы просто пишем имя нашей программы. Ничего сложного, главное наша фантазия.
Краткая характеристика области применения программы
Здесь описываем, в какой предметной области будет применяться наше творение. Для того чтобы было более понятно приведу пример из моей практики: Программа применяется для автоматизации учета имеющихся книжных изданий, имеющихся читателей, выдачи книжных изданий.
Сроки исполнения работ
Вот мы и подошли к одному из самых сложных пунктов. Наверное, многие читали байку о том, как программисты строят дом. Для тех, кто не слышал, обязательно прочитайте. Да я согласна ставить перед собой сроки выполнения работ тяжело. Часто мы не укладываемся в указанные нами сроки. С чем же это связанно? С тем, что мы не умеем планировать свое время, не можем правильно рассчитать количество ресурсов, которые нам понадобятся для достижения поставленной цели, также нельзя сбрасывать со счетов прочие форс-мажорные обстоятельства.
Вообще советую прочитать такие книги как:
- Фредерик Брукс: «Мифический человеко-месяц или как создаются программные системы»
- Йордан Э., Йордон Эдвард: «Путь камикадзе: Как разработчику программного обеспечения выжить в безнадежном проекте»
Описывать этот пункт в общих чертах и на основе своих проектов, довольно сложно. Нужно помнить, что проекты могут отличаться в корне: сложностью, количеством исполнителей, профессионализмом исполнителей и т.д. Поэтому просто скажу: читайте про управление проектами, в частности про Project Time Management.
Но программу мы пишем для конкретного заказчика, и не факт что заказчик не поставит перед нами какие-то свои сроки. Скорее всего, поставит. Что же нам делать в этом случае? Мы на время забываем про сроки, предложенные или навязанные заказчиком, и рассчитываем их самостоятельно. Дальше все будет зависеть от того, насколько наши сроки и сроки заказчика будут отличаться. Если они совсем не различаются или заказчик предлагает более длительный срок, мы соглашаемся. Ни в коем случае нельзя говорить заказчику: «Что это за гигантские сроки, мы справимся в 2 раза быстрее». Мы, конечно, теоретически сможем это сделать, а если мы сократим сроки и не успеем, мы останемся в «минусе». Поэтому некий запас во времени никогда не помешает. Мы рассмотрели оптимальный вариант, но сроки, предложенные заказчиком, могут оказаться меньше. Что же делать в таком случае? Вариантов немного – всего 3.
- Первый вариант: сразу же скажу он самый наихудший. Согласиться на эти сроки. Почему же? Если сроки чуть меньше наших, это не смертельно, но довольно опасно. Согласитесь, работать на износ довольно тяжело, но все-таки возможно, вот только не известно насколько это уменьшит реальные сроки, и уменьшит ли. Вообщем решать придется самостоятельно, во многом решение будет зависеть от того насколько вас заинтересует проект и какие риски появятся, если вы не уложитесь в сроки.
Но, если сроки отличаются сильно, и мы беремся за этот проект, проект сразу, же можно записывать в безнадежные, а нам готовить компенсацию заказчику, потому как зачастую заказчику не достаточно фразы: «подождите еще месяц и все будет сделано». Нет, конечно, заказчик может подождать месяц, но вот, если нам понадобится второй, заказчик задумается, и все может закончиться плачевно для нас. Заказчик сможет наказать нас рублем или еще хуже – обратиться в суд, нужно отметить, что основания для этого у него будут. Также может пострадать наша репутация, и если заказчику понадобится еще какая-либо программа, вероятно, что к нам он уже не обратится, еще и отговорит своих партнеров и просто знакомых.
Тут мы снова подошли к мысли о том, что ТЗ документ официальный. И если там написано, что мы должны завершить свою работу 12.12.2010, то мы должны это сделать.
- Второй вариант: отказаться от выполнения этого проекта.
- Третий вариант: самый наилучший для нас, но не факт что это устроит заказчика. Необходимо ему объяснить, что уложиться в сроки, предложенные им нереально. Сделать это нужно в доступной для его понимания форме.
В заключение хочу сказать, что начинать нужно именно с 3 варианта. Заказчик тоже человек, и если грамотно аргументировать, почему наше детище не может родиться быстрее определенного нами срока.
Заказчик
В данном пункте нет ничего нетривиального, просто пишем, кто является нашим родным и любимым заказчиком
Исполнитель
Данный пункт похож на предыдущий, но есть одна особенность, если мы работаем в команде, необходимо упомянуть обо всех участниках проекта, указать одного себя любимого недостаточно. Нет, конечно, это можно сделать, но в таком случае, за все косяки будем отвечать самостоятельно. Заказчику будет все равно, что это ошибка Васи, которого заказчик никогда не видел, и ранее о нем не слышал.
Основание для разработки
Еще один довольно важный пункт. В большинстве случаев помимо ТЗ, заказчик и исполнитель заключают договор, за подробностями обращаемся к гражданскому и трудовому кодексам. В ТЗ указываем, что был подписан договор на указание услуги по созданию программного продукта, указываем номер договора. Если договора нет, этот пункт будет отсутствовать.
Общая концепция системы
Для того чтобы написать этот пункт необходимо провести анализ предметной области для которой предназначена наша программа, определить какие бизнес-задачи будут решать с ее помощью. Но в данном пункте не требуется глубокий анализ, все это ждет нас впереди. Просто описываем, зачем же наше творение создается, и какой же от него будет толк. Для того чтобы более понятно приведу пример: Система позволяет организовать работу библиотекаря, систематизировать информацию об имеющихся книжных изданиях, студентах, преподавателях и сотрудниках использующих библиотеку.
Описание функциональности системы
Вот мы и подошли к одному из самых важных пунктов. Именно в этом пункте описываются функциональные требования к приложению. Если вдруг случится так, что заказчик предъявит нам претензии, это будет, чуть ли не первый пункт проверки экспертов. Поэтому его написанию стоит уделить особое внимание. Именно здесь в большей степени описывается то, что от нас хочет заказчик. Но не нужно забывать, что в половине случаев, заказчик сам не совсем понимает, что, же его душе хочется увидеть в нашем творении, и мы должны каким-то образом это из него вытянуть. Как уже писала в предыдущей статье, это отдельное искусство. Договоримся, что все функциональные требования были сформулированы, осталось их записать в ТЗ.
Как же это сделать? Если в системе представлено несколько категорий пользователей, мы должны это отразить. Кроме того все функции нужно разделить между этими категориями. Если такого разделения нет, то просто перечисляем функции, которые будет выполнять наше приложение.
Есть небольшой нюанс, если приложение добавляет/изменяет какие-либо данные, в скобках необходимо написать какие именно данные добавляются/изменяются. В противном случае, когда при сдаче программы в эксплуатацию заказчик скажет: «А почему в этой табличке нет поля телефон» мы не сможем ему аргументировано возразить. А в случае если мы укажем, какие именно поля содержит таблица, мы просто показываем заказчику документ, в котором написано что этого поля быть не должно.
Требования к информационным структурам и методам решения
Название данного пункта звучит страшно, но на самом деле ничего страшного и не понятно в нем нет. Просто описываем, какие технологии будут применяться в нашем приложении. Чтобы стало совсем понятно, приведу пример: система должна быть реализована согласно технологии «клиент-сервер»; В качестве сервера используется СУБД – сервер; Взаимодействие клиентской и серверной частей системы должно осуществляться согласно протоколу TCP/IP.
Требования к функциональным характеристикам
Этот пункт дублирует пункт Описание функциональности системы, только в более литературной форме. Также здесь описывается, каким образом реализуется взаимодействие с пользователем, например, при помощи набора первичный и вторичных форм.
Требования к обеспечению надёжного функционирования системы
Вот мы и добрались до формальных пунктов, которые пишутся по шаблону. В данном пункте описывается что должен предпринимать заказчик для того чтобы наша программа работала надежно. Просмотрев большое количество ТЗ, я пришла к выводу, что текст данного пункта везде одинаков, поэтому просто приведу его ниже.
Надежное (устойчивое) функционирование программы должно быть обеспечено выполнением Заказчиком совокупности организационно-технических мероприятий, перечень которых приведен ниже:
- Организацией бесперебойного питания технических средств;
- Использованием лицензионного программного обеспечения;
- Регулярным выполнением рекомендаций Министерства труда и социального развития РФ, изложенных в Постановлении от 23 июля 1998 г. «Об утверждении межотраслевых типовых норм времени на работы по сервисному обслуживанию ПЭВМ и оргтехники и сопровождению программных средств»;
- Регулярным выполнением требований ГОСТ 51188-98. Защита информации. Испытания программных средств на наличие компьютерных вирусов;
Типы отказов
Следующий пункт, текст которого тоже не меняется. Здесь мы просто описываем, какие типы сбоев возможны. В процессе работы системы могут случаться отказы следующих типов:
- Сбои в подсистеме работы с сетевыми соединениями (ошибки, связанные с передачей информации между сервером и клиентами, а также ошибки при работе с базой данных системы);
- Отказы, вызванные сбоем электропитания технических средств (иными внешними факторами);
- Отказы, вызванные неисправностью технических средств;
- Отказы, вызванные не фатальным сбоем (не крахом) операционной системы;
- Отказы, вызванные фатальным сбоем (крахом) операционной системы.
Время восстановления после отказа
Этот пункт напрямую связан с предыдущим. Мы просто указываем, какое количество времени понадобится на восстановление работы нашего приложения при возникновении сбоев типы, которых описаны выше. Причем конкретное время в минутах указывать не обязательно. Допустим, если произошел отказ, вызванный фатальным сбоем операционной системы, достаточно написать: время восстановления не должно превышать времени, требуемого на устранение неисправностей технических средств и переустановки программных средств.
Допустимые потери данных при отказе
Каким бы надежным приложением не было наше приложение, сбои в его работе и работе операционной системы и технических средствах возможны. Для того чтобы заказчик знал чего же ему ждать после сбоя как раз и пишется этот пункт. Мы, конечно же, мы можем написать, что при сбое данные потеряны, не будут. К сожалению это вариант утопический. Полная противоположность этому варианту, данные будут потеряны полностью. Но это не устроит нашего любимого заказчика. Думаю, это никого не устроит, тем более, когда транзакциями, механизмами резервного копирования и восстановления никого не удивишь. Думаю для того чтобы стало понятно что писать, я приведу пример: при сбое в подсистеме работы с сетевыми соединениями допускается потеря информации, относящейся к тому справочнику или к той читательской карточке, о которой информация передавалась по каналу связи в момент сбоя. Главным критерием при определении допустимых потерь информации при сбое в перечисленных компонентах является сохранение целостности данных системы.
Важная информация, которая должна быть защищена от разрушения
Почти в каждом приложении есть информация, которая всегда должна оставаться целостной. Данный пункт предназначен для того чтобы зафиксировать что именно относится к наиболее важной информации, какие именно данные необходимо обезопасить в первую очередь. Допустим, что наше приложение работает с какой-либо БД, то, прежде всего, необходимо обеспечить целостность этой БД.
Отказы из-за некорректных действий пользователей системы
Всегда нужно помнить о том, что пользователи бывают разные. Исходя из личного опыта, половина из них общается с компьютером на Вы. Следовательно, наше творение должно терпеть все нападки таких пользователей и не падать. Поэтому срочно вспоминаем про try catch =) Нет, конечно, можно не обрабатывать ошибочные ситуации, но это не правильно. Поэтому в данном пункте пишем, что такие отказы не возможны и реализуем это.
Климатические условия эксплуатации
Работа программы зависит от того сможет ли работать технические средства в данных климатических условиях, поэтому пишем: климатические условия эксплуатации, при которых должны обеспечиваться заданные характеристики, должны удовлетворять требованиям, предъявляемым к техническим средствам в части условий их эксплуатации.
Требования к квалификации и численности персонала
Здесь указываем минимальное количество персонала, который будет работать с нашей программой, также описываем требования к их образованию. Также для каждого пользователя указываем, какие задачи он будет решать, используя наше приложение.
Требования к составу и параметрам технических средств
Все мы хотя бы раз играли в компьютерные игры, держали коробочку от диска, на которой пишут какими характеристиками должен обладать компьютер, чтобы мы могли насладиться игрой. Вот замечательный пример, иллюстрирующий данный пункт ТЗ.
Требования к исходным кодам и языкам программирования
Данный пункт предназначен для отображения прихотей очень привередливых заказчиков разбирающихся в языках программирования. Если по каким-то причинам заказчик просит или требует, чтобы приложение было написано на конкретном языке, именно это отмечаем в данном пункте. Также здесь отмечаем, хочет ли получить заказчик исходники программы.
Требования к программным средствам, используемым программой
Здесь описываем, что же из стороннего софта необходимо для работы нашей программы, начиная с операционной системы и заканчивая каким-нибудь ODBC-драйвером.
Требования к защите информации и программы
Нам может несказанно «повести» и заказчик скажет, что в его приложении будет обрабатываться коммерческая тайна или еще хуже персональные данные или государственная тайна. В таком случае нам придется читать различные ФЗ и реализовывать все требования описанные там. А в ТЗ необходимо отметить какие именно требования по защите информации были выполнены. Но все может быть проще в том случае если заказчик просто попросит сделать авторизацию или что-то подобное.
Если же заказчик не предъявляет никаких требований к защите информации, мы должны не забыть указать это, чтобы исключить какие-либо вопросы при сдаче проекта.
Маркировка и упаковка
В данном пункте описывается, по какому принципу будут нумероваться версии данной программы. Также указывается, на каких носителях программа будет распространяться.
Транспортировка и хранение
Увидев этот пункт впервые, я улыбнулась, потому как что в нем писать не понятно. До сих пор данный пункт остается загадкой, поэтому просто приведу, если можно так выразить свою отписку: специальных требований к транспортировке и хранению не предъявляется.
Специальные требования
Для чего нужен данный пункт? Поясню, если у заказчика остались требования, которые мы не сможем включить ни в один из предыдущих пунктов, то записываем их сюда. Зачем их вообще записывать? Не забываем, что именно ТЗ определяет «все ли мы сделали» и в нем должны быть указаны все требования заказчика.
Вместо заключения
Вот я и рассказала вам о первых четырех главах ТЗ, надеюсь, что вам после прочтения уже не страшно при упоминании ТЗ, вы уже имеете представление о том, что и как в нем писать. В дальнейшем, расскажу об оставшихся моментах.
Источники
- ГОСТ 19.201-78 Техническое задание, требования к содержанию и оформлению http://www.nist.ru/hr/doc/gost/19201-78.htm
- ГОСТ 19.106-78 Требования к программным документам, выполненным печатным способом. http://www.nist.ru/hr/doc/gost/19106-78.htm
- «В круге разработки» Наталья Дубова http://citforum.ru/SE/project/circle
- Единая система программной документации (ЕСПД) http://www.philosoft.ru/espd.zhtml
- Комплексный/Унифицированный процесс разработки ПО http://www.rup-rus.ru
- Введение в управление проектами http://www.prjman.ru/theory/32
Статья из девятого выпуска журнала «ПРОграммист».
Облако меток
ассемблер timer TBitMap select SaveToFile ShellExecute программы массив советы word MySQL SQL ListView pos random компоненты дата LoadFromFile form база данных сеть html php RichEdit indy строки Win Api tstringlist Image мысли макросы Edit ListBox office C/C++ memo графика StringGrid поиск canvas файл Pascal форма Файлы интернет Microsoft Office Excel excel winapi журнал ПРОграммист DelphiКупить рекламу на сайте за 1000 руб
пишите сюда - alarforum@yandex.ru
Да и по любым другим вопросам пишите на почту

пеллетные котлы

Пеллетный котел Emtas
Наши форумы по программированию:
- Форум Web программирование (веб)
- Delphi форумы
- Форумы C (Си)
- Форум .NET Frameworks (точка нет фреймворки)
- Форум Java (джава)
- Форум низкоуровневое программирование
- Форум VBA (вба)
- Форум OpenGL
- Форум DirectX
- Форум CAD проектирование
- Форум по операционным системам
- Форум Software (Софт)
- Форум Hardware (Компьютерное железо)


