Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Вопросы по Delphi (до версии 2009) - часть 6

Автор: vladok_7
Дата сообщения: 22.08.2012 14:03
Всем привет, я начинаю изучать делфи по книге "Валерия Рубанцева" а
мне кое-что не понятно!

там написано

const
num= 123;
pi= 3.1415926
Flag= TRUE
//мне не понятно для чего нужны флаги! и для чего он нужен


var s: single; //и что такое сингл тоже не понятно

begin
s:= num;
s:= pi;
s:=flag;

. . .

И НАПИСАНО : В данном примере действительной переменной s можно присвоить значение целого типа или действительного типа ,но никак не логического или строкового!!!
ЧТО ОБЪЯСНИЛИ НЕ ПОНЯТНО!!!!
Автор: XPerformer
Дата сообщения: 22.08.2012 14:06
vladok_7
В книжке должно быть написано что такое single - это тип, позволяющий хранить дробные значения. Такие переменные могут хранить и целые значения как частный случай дробных, но не других типов
Автор: vladok_7
Дата сообщения: 22.08.2012 14:10
Всем привет, я начинаю изучать делфи по книге "Валерия Рубанцева" а
мне кое-что не понятно!

там написано

const
num= 123;
pi= 3.1415926
Flag= TRUE
//мне не понятно для чего нужны флаги! и для чего он нужен


var s: single; //и что такое сингл тоже не понятно

begin
s:= num;
s:= pi;
s:=flag;

. . .

И НАПИСАНО : В данном примере действительной переменной s можно присвоить значение целого типа или действительного типа ,но никак не логического или строкового!!!
ЧТО ОБЪЯСНИЛИ НЕ ПОНЯТНО!!!!

Добавлено:
а что такое char
Автор: XPerformer
Дата сообщения: 22.08.2012 14:19
vladok_7
char - это один символ. может, стоит другую книжку взять...
Автор: vladok_7
Дата сообщения: 22.08.2012 14:22
посоветуй какую книгу по дельфе купить
Автор: XPerformer
Дата сообщения: 22.08.2012 14:28
Фаронов Архангельский Тейксейра
там есть предметный указатель, можно незнакомые слова по указателю смотреть
Автор: A_V
Дата сообщения: 22.08.2012 14:54
Aleksandr N
ИМХО, в общем случае, нельзя (ну если не скрывать предварительно дочерние окна ) ).
вообще странный подход, ты хочешь, что-бы, к примеру, Label отрисовался, а StaticText - нет..
Автор: Aleksandr N
Дата сообщения: 22.08.2012 16:46
Вот только запостил вопрос сразу нашелся ответ, хотя ковырялся три недели переставляя переменные.
Ответ, может кому-то пригодится:
После CallWindowProc нужно поставить ещё один CallWindowProc, но только вместо проецирования на нужный контрол проецировать в память:

CallWindowProc(OldNotifyWndProc, hNotifyWnd, WM_PRINTCLIENT, hMemoryDC, PRF_ERASEBKGND or PRF_CLIENT);

Вот только образовался странный косяк. Хотя я и смещаю начало координат функцией SetWindowOrgEx по X и Y и на нужном контроле нормально рисуется фон родителя, то при проецировании в память смещения по Y почему-то не происходит...

Добавлено:
A_V
Пока писал и ты ответил...
Если быть честным, я делая для себя программку, которая рисует свои часы вместо стандартных в трее со всеми вытекающими...
Сделать свою прозрачную картинку и наложить её на очищенные от текста системные часы не получилось, поэтому решил забрать фон под часами, нарисовать на нём и всё это нарисовать на часах. А у меня всё время получалось наложение новой картинки на старую, хотя я как-бы старую стирал... Наверное стёрка была китайская, вот и не стирала...
Достаточно посмотреть на компонент TrayClock, который есть в нашем варезнике и станет понятен принцип.

Спасибо.
Автор: vladok_7
Дата сообщения: 22.08.2012 20:54
люди объясните плизз как это понять! (я новичок)

Глобальные переменные объявляютсю в секции INTERFACE МОДУЛЯ. Локаляные- в ПРОЦЕДУРАХ И ФУНКЦИЯХ.
Автор: V1s1ter
Дата сообщения: 22.08.2012 21:17
vladok_7
Модуль (unit) делется на две части, первая начинается словом interface, а вторая словом implementation.
Все переменные, константы, типы, объекты и т.д. находящиеся после слова interface и до слова implementation можно использовать как и в том модуле где они объявлены/, так и в других модулях.
Все переменные, константы, типы, объекты и т.д. находящиеся после слова implementation можно использовать только в том модуле где они объявлены. Например Pi, a, b, с можно использовать в модуле MyUnit1 и в модуле MyUnit2, а вот Eps, x, y, z можно использовать только в модуле MyUnit1.
Дла того чтобв в модуле MyUnit2 можно было импользовать переменные, константы, типы, ... из другого модуля нужно дать прописать в секции uses название модуля который будем использовать, в примере это MyUnit1.

Код:
---- файл MyUnit1.pas
unit MyUnit1;

interface
const
Pi = 3.14;
var
a, b, c: Integer;

implementation
const
Eps = 0.001;
var
x, y, z: Integer;

end.

---- файл MyUnit2.pas
unit MyUnit2;
uses
MyUnit1;

implementation
...
...
a := Pi; <--- правильно
x := 0; <--- ошибка

end.
Автор: Wahnsinn
Дата сообщения: 22.08.2012 21:22
vladok_7
Если погуглить за тебя
Глобальные переменные — это переменные, объявленные за пределами функции или процедуры.
Глобальные переменные создаются во время запуска приложения, существуют, пока оно выполняется, и уничтожаются по завершении его работы. Эти переменные не только доступны в течение всего времени работы приложения, но и являются общедоступными.
Любая создаваемая процедура или функция может обращаться к общедоступным переменным. Единственное исключение из этого правила — глобальная переменная, объявленная в разделе реализации модуля. В этом случае переменная остается глобальной, но доступна только в том модуле, в котором она объявлена.
Примеры

Код:
unit Unit1;
interface
var
s: string; { global variable that can be used in other units }
implementation
var
i: Integer; { global variable, but can only be used in this unit }
end.
Автор: V1s1ter
Дата сообщения: 22.08.2012 21:24
Да, забыл
Переменные и константы написаные после слова procedure или function и словом begin можно использовать только в этой процедуре, тоесть между первым begin процедуры и соответствубщему ему end.

Код:
procedure MyProc;
var
i, N, Q: Integer;
begin
...
Q := 4; <--- правильно
...
for i := 0 to N do
begin
Q := Q+2; <--- правильно
end;
end;

Q := 0; <--- неправильно
Автор: Aleksandr N
Дата сообщения: 22.08.2012 21:45

Цитата:
Вот только образовался странный косяк. Хотя я и смещаю начало координат функцией SetWindowOrgEx по X и Y и на нужном контроле нормально рисуется фон родителя, то при проецировании в память смещения по Y почему-то не происходит...

Продолжу свой ответ для информации.
Функцией SetWindowOrgEx я сместил координаты для контрола, а для отображения в памяти - не подумал. Нужно добавить перед вызовом CallWindowProc:

SetWindowOrgEx(hMemoryDC, DeltaPosX, GetWindowSize(hNotifyWnd) - GetWindowSize(h_Wnd), nil);

Ещё раз всем спасибо.
Автор: vladok_7
Дата сообщения: 22.08.2012 21:52
спасибо те V1s1ter огромное!
Wahnsinn тебе тоже спасибо!
Автор: Frodo_Torbins
Дата сообщения: 23.08.2012 10:47
vladok_7
Какую то очень неудачную книгу вы себе выбрали. Поищите в интернете книжки, о которых много положительных отзывов, можно даже времен делфи 5. Когда подберете себе парочку таких книжек, можно будет поискать их на развалах б/у книг, или распечатать.
Автор: Maks150988
Дата сообщения: 25.08.2012 14:58
A_V

Цитата:
Потому что обычно ф-ии (lstrcpyn) принимают кол-во символов, а не размер в байтах

А, точно, забыл. Изначально я вобще использовал CopyMemory. Там как раз количество байт надо указывать.
Автор: Dimrix
Дата сообщения: 26.08.2012 18:19
Курил гугль несколько дней, но не получилось найти толкового решения "програмной" установки драйверов из програмки на Делфи. Задача следующая: девайс со встроенной флехой. При подключении флеха находится самой последней. На ней и будет находится моя програмка. Необходимо поставить драйвера и заставить винду "обновить" драйвер на устройство. Находил несколько вариантов, но везде были но:
1. Было предложение "запуска" инфа-файла драйвера, но может они и ставятся, но при "втыкивании" устройства оно не определяется системойнаходится.
2. Перекачал несколько программ по бекапу/восстановлению драйверов: но при восстановлении везде выпадают диалоги с кнопками и прочей фигней, а хочется что бы автоматом ставились с наименьшими вмешательствами пользователя. Перехватывать окна и нажимать кнопки - не красиво (хотя это пока единственный вариант).

P.S. По гуглив ещё чуток, нарыл информацию о некой библиотеке виндовс difxapi.dll в которой есть функции DriverPackageInstall/DriverPackageUninstall, но реализации нашёл только под Си. Попробовал сам перевести, но толи я хреновый "переводчик", толи где то ошибку сделал в вызове функции. Код:

const
DifxApiModuleName = 'DIFxAPI.DLL';
const
DRIVER_PACKAGE_FORCE = $00000004;
DRIVER_PACKAGE_LEGACY_MODE = $00000010;
type
PCINSTALLERINFO_W = ^PCINSTALLERINFO_W;
INSTALLERINFO_W = packed record
pApplicationId, pDisplayName, pProductName, pMfgName: PAnsiChar;
end;
TPCINSTALLERINFO_W = INSTALLERINFO_W;
function DriverPackageInstall(DriverPackageInfPath: PAnsiChar; Flags: DWORD;
pInstallerInfo: PCINSTALLERINFO_W; pNeedReboot: Boolean): DWORD; stdcall; external DifxApiModuleName
name 'DriverPackageInstall';
Это из:
define DRIVER_PACKAGE_FORCE 0x00000004
define DRIVER_PACKAGE_LEGACY_MODE 0x00000010

typedef struct
{
PWSTR pApplicationId;
PWSTR pDisplayName;
PWSTR pProductName;
PWSTR pMfgName;
} INSTALLERINFO_W, * PINSTALLERINFO_W;

typedef const PINSTALLERINFO_W PCINSTALLERINFO_W;

WINDIFXAPI
DWORD
WINAPI
DriverPackageInstallW(
PCWSTR DriverPackageInfPath,
DWORD Flags,
PCINSTALLERINFO_W pInstallerInfo,
BOOL * pNeedReboot
);
Ну и вызывал так:

procedure TForm1.SpeedButton1Click(Sender: TObject);
const
lqrInfFile: String = 'cm_mdm.inf';
var
NR: Boolean;
Res: DWORD;
begin
Res := DriverPackageInstall (PChar (lqrInfFile), DRIVER_PACKAGE_FORCE or DRIVER_PACKAGE_LEGACY_MODE, nil, NR);
if (Res <> 0) then

end;
end;
Возвращает Res=2, что означает файл не найден. (Файл лежит в папке с програмкой, пробовал указать полный путь - таже фигня).
Автор: Dimrix
Дата сообщения: 27.08.2012 14:37
Вопрос снимается ввиду самостоятельного решения. Кому интересно - пишите в ПМ поделюсь...
Автор: shadow user777
Дата сообщения: 27.08.2012 15:00
Уххх, почитал страницы темы, аж дух захватывает и зависть берёт.
Мне бы такие познания в этой области .... К сожалению таковыми не обладаю, и по специальности очень далёк от программирования.
Хочу попросить помощи. Мне кажется что задача которая у меня нарисовалась, для человека имеющего навыки весьма проста, но для меня она из области сверхъестественного.
Нужна обычная длл под Windows.
1. Ищем процесс в памяти по имени (LoginUS.exe)
2. Получаем название родительского процесса (Run.exe)
3. Если родительский процесс другой - завершаем работу процесса LoginUS.exe(закрывает)
4. Если родительский процесс соответствует (Run.exe), то получаем путь родительского процесса.
5. Вычисляем хэш родительского процесса и сравниваем с эталонным хэшем (эталонный хранится в коде dll).
6. Если хэш совпадает - ничего не делать (или повторить проверку через 3-5 минут). Если хэш не совпадает - завершает работу процесса LoginUS.exe (закрывает)

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

Прошу сильно не пинать что вот так напрямую обратился за изготовлением, но других вариантов кроме как кинуть клич о помощи я не нашел.
Автор: Aleksandr N
Дата сообщения: 27.08.2012 16:59
Есть стандартная задача - не допустить запуска второй копии программы и её реализация, которую можно найти на любом сайте:

function NewWndProc(Handle: HWND; Msg: Integer; wParam, lParam: Longint): Longint; stdcall;
begin
Result := 0;
if Msg <> MessageID then
Result := CallWindowProc(WProc, Handle, Msg, wParam, lParam);
end;

function InitInstance: Boolean;
var BSMRecipients: DWORD;
begin
WProc := TFNWndProc(SetWindowLong(Application.Handle, GWL_WNDPROC, Longint(@NewWndProc)));
if WProc = nil then
begin
Result := False;
Exit;
end;
MutHandle := OpenMutex(MUTEX_ALL_ACCESS, False, UniqueAppStr);
if MutHandle = 0 then
begin
Result := True;
MutHandle := CreateMutex(nil, False, UniqueAppStr);
if MutHandle = 0 then
Result := False;
end
else
begin
BSMRecipients := BSM_APPLICATIONS;
BroadCastSystemMessage(BSF_IGNORECURRENTTASK or BSF_POSTMESSAGE, @BSMRecipients, MessageID, MI_QUERYWINDOWHANDLE, Application.Handle);
Application.ProcessMessages;
Result := False;
end;
end;

Если одна копия уже запущена и вручную запускать вторую - всё нормально, запус не происходит. Но я поставил программу в автозагрузку. По непонятной причине Виндовс дважды пытается запустить программу. В этом случае, примерно в 80% происходит запуск второй копии программы.

Что в этом коде может быть не так/не дописано? Как 100% не допустить вторую копию?
(В интернете видел кучу способов - либо слишком простые, либо не подходят, либо глючные)
Автор: MrZeRo
Дата сообщения: 27.08.2012 17:35
Aleksandr N
непонятно зачем так много кода, в частности BroadcastSystemMessage, переопределение оконной функции и т.д.
Вот тут достаточно толково написано и в коде ничего лишнего:
хттп://www.delphimaster.ru/articles/limit.html
Автор: Aleksandr N
Дата сообщения: 27.08.2012 17:51
MrZeRo
Ну не знаю, считаю что просто CreateMutex - это слишком просто, а, по моему, про CreateSemaphore слышал, что если что пойдёт не так семафор остается в памяти и поможет только перезагрузка.

Добавлено:
К таму-же в не зависимости от BroadcastSystemMessage проверки на CreateMutex в моём коде ведёт себя неадекватно.

Может ещё кто-нибудь что-нибудь подскажет?
Автор: shadow user777
Дата сообщения: 27.08.2012 21:01
Найденные в инете сорцы:
Вычисление хэш МД5 файла.
http://pastebin.com/ESDT6eEm
Определение родительского процесса.
http://pastebin.com/0cgcp1sk

Это я что бы облегчить труд того, кто может быть возьмется сделать мою просьбу.
Автор: MrZeRo
Дата сообщения: 27.08.2012 22:02
Aleksandr N
Удивительные у вас сведения про CreateSemaphore, если это правда (хотя бы на треть), то нужно просто-таки запретить всем пользоваться этой функцией, вычеркнуть ее из документации и навсегда забыть и книжки с ее упоминанием, в частности Рихтера "Windows для профессионалов" предать анафеме во веки веков.
Можно ли узнать, в чем "неадекватность" кода основанного на CreateMutex (не тот путаный, что вы привели, а тот короткий и внятный, который опубликован по ссылке, которую я дал выше) и чем конкретно не устраивает этот подход? Если он простой, то еще не значит, что нерабочий, у меня подобный код прекрасно работал.
Есть другие подходы, но они хуже. Например, если приложение имеет главное окно, то можно при помощи FindWindow найти, существует ли такое окно и если да, то считать, что приложение уже запущено - реализация простая, но есть недостатки: медленно и не очень надежно.
Можно еще попытаться поискать по имени процесса через EnumProcesses, но тут нужны права админа на машине, иначе вы не увидите процесс (вашу программу), запущенный другим пользователем, пример тут: хттп://www.delphisources.ru/pages/faq/base/get_active_apps.html (этот не проверял, но идея понятна).
Автор: Aleksandr N
Дата сообщения: 27.08.2012 22:17
MrZeRo

Цитата:
Удивительные у вас сведения про CreateSemaphore

Я просто где-то читал, не утверждаю, что испытал на своей шкуре.
Возможно без лишнего кода CreateMutex сработает, проверю - отпишусь. Просто мне показалось что это слишком просто.
Поиск процесса знаю - не подходит, по окну - принципиально не подходит.
Автор: MrZeRo
Дата сообщения: 28.08.2012 09:31
Aleksandr N
И еще вдогонку один момент. На самом-то деле нельзя "запретить" собственно запуск второй копии приложения, можно только в начале выполнения вашей программы узнать как можно раньше (это самое важное!) что уже такая программа запущена и выйти. В этой связи имеет смысл воспользоваться подходом описанным в статье по моей ссылке: разместить соответствующий код проверки в отдельном модуле и этот модуль подключить первым.

По поводу подходов, еще существует подход с Memory Mapped Files (файлы отображаемые в память), можно найти у Рихтера, там аналогично мьютексам, но надо писать больше кода, а результат тот же самый.
Автор: Aleksandr N
Дата сообщения: 28.08.2012 16:38
MrZeRo
Вот зараза, на виртуалке повторного запуска приложения с моим кодом не происходит. Это бывает только на основной системе. Нужно найти время чтобы чтобы поиздеваться над осью...
Про отображение в памяти тоже знаю, использую в этой программе но для других целей. Не хотелось этот способ ещё и в этих целях использовать, но если будет работать, то придётся.
Автор: OOD
Дата сообщения: 29.08.2012 09:27
Подскажите пожалуйста что не так :
ShellExecute(Handle,nil,'msinfo32.exe /report C:\config.txt',nil,nil,SW_HIDE);
Параметры запуска
Код: /report C:\config.txt
Автор: Frodo_Torbins
Дата сообщения: 29.08.2012 12:45
OOD
Параметры запуска экзешника вписываются в отдельно в следующий параметр функции.
Автор: OOD
Дата сообщения: 29.08.2012 12:57
Все равно окно сведения о системе продолжает висеть
ShellExecute(Handle,nil,'msinfo32.exe','/report config.txt',nil,SW_HIDE);

Страницы: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374

Предыдущая тема: MPO File


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.