Compare only time portion delphi given time in string - delphi

I want to execute code if the now time is over a certain time given in a string:
var
Time,mynowtime:TTime;
begin
mynowtime := ('24:00:00');
Time := Frac(Now);
if Time > mynowtime then
begin
ShowMessage(TimeToStr(Time));
end;
It gives me an error:
'24:00:00' is not a valid date and time.

as Ken White and Remy Lebeau said in Their comments, you can do it like this;
if CompareTime(Time(), EncodeTime(23, 0, 0, 0)) > 0 then
ShowMessage('it''s late');
if the time value is coming from an external source;
var
FmtStngs: TFormatSettings;
Begin
GetLocaleFormatSettings( GetThreadLocale, FmtStngs );
// set format settings, for more info have a look at the link below
if CompareTime(Time(), StrToTime('23:00:00', FmtStngs)) > 0 then
ShowMessage('it''s late');
End;
link

Related

Delphi 7: How to use a combination of check boxes

Am working an a small app in Delphi7 but am puzzles on how to use a combination of 3 check boxes
Example: if check.box1 and checkbox2 checked run system application with these prefs
or if checkbox1 only checked run system application with these prefs or if checkbox2 only checked run with these prefs
It sounds like you're having trouble getting started writing what you need, which is basically a series of if..then..else flow-control statements based on compound boolean expressions. You probably want a structure like the one below. I'm not going to show you the entire thing, because it's best for you to work it out for yourself, but this should give you the idea:
if (CheckBox1.Checked) and (CheckBox2.Checked) and not (CheckBox3.Checked) then
begin
// do one thing
end
else
begin
if (CheckBox1.Checked) and not (CheckBox2.Checked) and not (CheckBox3.Checked) then
begin
// do another thing
end
else
// etc
end;
If you're familiar with enumerated types, you might do better to declare one and use that to derive the selected preferences and then act upon them. The point of doing that is twofold: to increase the clarity of your code (at the expense of your code being longer, of course); and to separate the logic for calculating which preference the user has selected from the code which acts upon it.
Something like
type
TRunPreference = (rpNone, rpOne, rpTwo, rpThree, rpFour,
rpFive, rpSix, rpSeven, rpEight);
// rpOne..rpEight are for the 8 permutations of three booleans
// and the rpNone is to provide for initialising the variable
// with something which isn't one of the desired values
var
RunPreference : TRunPreference;
procedure TForm1.Button1Click(Sender: TObject);
begin
RunPreference := rpNone;
if (CheckBox1.Checked) and (CheckBox2.Checked) and not (CheckBox3.Checked) then
begin
RunPreference := rpOne;
end
else
begin
if (CheckBox1.Checked) and not (CheckBox2.Checked) and not (CheckBox3.Checked) then
begin
RunPreference := rpTwo;
end
else
; //
end;
case RunPreference of
rpNone :
; // do nothing
rpOne :
begin
// Act on rpOne
end;
rpTwo :
begin
// Act on rpTwo
end;
// etc
end; { Case of RunPreference }
end;
Inspired by MartynA's solution, and because I prefer compact code, here's how I would do it:
// For the three (sets of?) preferences, define bit values, and
// a variable to hold the combination of the selected preferences:
const
PrefA=1; PrefB=2; PrefC=4;
var
prefs: byte;
procedure TForm12.Button2Click(Sender: TObject);
begin
// whether a preference should be active or not becomes a simple `OR` function
// based on each checkbox's state
prefs := 0;
if CheckBox1.Checked then prefs := prefs or PrefA;
if CheckBox2.Checked then prefs := prefs or PrefB;
if CheckBox3.Checked then prefs := prefs or PrefC;
// then use a `case` statement to run according the preference combination
// The values like `PrefA or PrefC` can be used instead of numeric values,
// since they can be resolved at compile time.
// Whether they improve readability or not is ... (disputable)
case prefs of
0:
ShowMessage('Running without preferences');
PrefA:
ShowMessage('Running with PrefA alone');
PrefB:
ShowMessage('Running with PrefB alone');
PrefA or PrefB:
ShowMessage('Running with PrefA and PrefB');
PrefC:
ShowMessage('Running with PrefC alone');
PrefA or PrefC:
ShowMessage('Running with PrefA and PrefC');
PrefB or PrefC:
ShowMessage('Running with PrefB and PrefC');
PrefA or PrefB or PrefC:
ShowMessage('Running with PrefA and PrefB and PrefC');
end;
end;
If you need to check in your code whether a preference is active or not, you can do it like:
if (prefs and PrefB) then
// do whatever requires PrefB to be selected

How to transfer a scanned image from WIA ImageFile to TBitmap without saving it to disk?

I'm using this code to acquire the scanned image from WIA:
const
wiaFormatJPEG = '{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}';
wiaFormatPNG = '{B96B3CAF-0728-11D3-9D7B-0000F81EF32E}';
var
CommonDialog: ICommonDialog;
AImage: IImageFile;
i: Integer;
begin
CommonDialog := CreateOleObject('WIA.CommonDialog') as ICommonDialog;
for i := 1 to Scanner.Properties.Count do
begin
if (Scanner.Properties[i].Name = 'Horizontal Resolution') or
(Scanner.Properties[i].Name = 'Vertical Resolution') then
Scanner.Properties[i].Set_Value(72)
else if Scanner.Properties[i].Name = 'Horizontal Extent' then
Scanner.Properties[i].Set_Value(Round(8.27 * 72))
else if Scanner.Properties[i].Name = 'Vertical Extent' then
Scanner.Properties[i].Set_Value(Round(11.00 * 72));
end;
AImage := IUnknown(CommonDialog.ShowTransfer(Scanner, wiaFormatPNG, True)) as IImageFile;
//Save the image
AImage.SaveFile('D:\1.' + AImage.FileExtension);
imgImage.Picture.LoadFromFile('D:\1.' + AImage.FileExtension);
DeleteFile('D:\1.' + AImage.FileExtension);
end;
Scanner is initialized using this code:
Scanner := DevMgr.DeviceInfos[Integer(cbWIASource.Items.Objects[cbWIASource.ItemIndex])].Connect.Items[1];
And DevMgr and cbWIASource are initialized using this code:
DevMgr := CreateOleObject('WIA.DeviceManager') as IDeviceManager;
for i := 1 to DevMgr.DeviceInfos.Count do
for j := 1 to DevMgr.DeviceInfos[i].Properties.Count do
if DevMgr.DeviceInfos[i].Properties[j].Name = 'Name' then
begin
cbWIASource.Items.AddObject(DevMgr.DeviceInfos[i].Properties[j].Get_Value, TObject(i));
Break;
end;
I was wondering if there is a way to copy the scanned document without first saving it to the disk. I read on MSDN that I can access ARGBData member of ImageFile to access pixel data, but is there a simple way to copy the entire image from FileData to TBitmap? For instance, can I use a TMemoryStream?
Just as an update, I found this example on MSDN. I know nothing about VB, but I guess the Picture object is a wrapper around HBITMAP. So, is it logical to conclude that the ImageFile.Picture property is what I need?
IImageFile has a property FileData with provides access to the binary image data, via IVector.BinaryData

Scan entire process memory with ReadProcessMemory

I'm tryin to scan an entire process memory but no success... What I'm doing is: for tests I'm using notepad, so I write there %B and this values in HEX are: 25(%) and 42(B). So the code is:
while (VirtualQueryEx(PIDHandle, Pointer(MemStart), MemInfo, SizeOf(MemInfo)) <> 0) do
begin
if ((MemInfo.State = MEM_COMMIT) and (not (MemInfo.Protect = PAGE_GUARD)
or (MemInfo.Protect = PAGE_NOACCESS)) and (MemInfo.Protect = PAGE_READWRITE)) then
begin
SetLength(Buff, MemInfo.RegionSize);
if (ReadProcessMemory(PIDHandle, MemInfo.BaseAddress, Buff,
MemInfo.RegionSize, ReceivedBytes)) then
begin
for I := 0 to SizeOf(Buff) do
begin
if (IntToHex(Buff[i], 1) = '25') and (IntToHex(Buff[i+2], 1) = '42') then
Form1.Memo1.Lines.Append(IntToHex(Buff[i], 1));
end;
end;
end;
MemStart:= MemStart + MemInfo.RegionSize;
end;
CloseHandle(PIDHandle);
end;
The var 'Buff' is TBytes (I read about TBytes and think it's same as array of byte). So I'm converting the bytes to Hex, and searching for values: 25 and 42 respectively. The code is like:
if (IntToHex(Buff[i], 1) = '25') and (IntToHex(Buff[i+2], 1) = '42') then
Because have 00 between the hex values. So I need to add '+2'. How can I scan the entire memory for this values??
Notepad uses Unicode so you'll need to look for UTF-16 encoded data, $0025 and $0042.
I don't understand why you feel the need to convert into hex strings before comparing. There's nothing special about hex that requires the use of strings. Hexadecimal is just a number system with base-16. So, decimal 32 is the same as hexadecimal 20, i.e. 32=$20. Do your comparison directly with integral values:
if (Buff[i]=$25) and (Buff[i+2]=$42) then
That said, taking into account the $00 bytes your test should really be something like this:
var
Target: string;
....
Target := '%B';
if CompareMem(#Buff[i], #Target[1], Length(Target)*SizeOf(Char)) then
....
I don't want to get too deep into the rest of your code, but this line
for I := 0 to SizeOf(Buff) do
is wrong on many different levels.
SizeOf(Buff) returns the size of a pointer since a dynamic array variable is essentially just a pointer. A useful thing to remember is that SizeOf is evaluated at compile time.
If you used Length instead of SizeOf then you would be iterating over the end of the list. To loop over a dynamic array, loop from 0 to Length(...)-1.
But in this case you are accessing index i+2 inside the loop, so you should loop from 0 to Length(...)-3.
But in fact you need to compare against 4 consecutive bytes to find a match. Perhaps like this:
TargetByteLength = Length(Target)*SizeOf(Char);
for i := 0 to Length(Buff)-TargetByteLength do
if CompareMem(#Buff[i], #Target[1], TargetByteLength) then
....

Cant find simple error in Delphi Insertion Sort algorithm

I am using insertion sort to sort a stringlist (EmailingListArray below).
EmailingListArray[1] is an array that contains names.
EmailingListArray[2] contains corresponding emails.
I am sorting EmailingListArray[1] and when something changes within it, it also changes the second array, so they are sorted together.
An awkward way of doing things, I know, but it's for coursework and I wanted to put an insertion sort in somewhere to try get an extra mark :L
Here's my code
//quick check to make sure array contains correct values
for first := 0 to EmailingListArray[1].Count do
ShowMessage(EmailingListArray[1][first]);
//then sort
First := 0;
Last := EmailingListArray[1].Count;
for CurrentPointer := First +1 to Last-1 do
begin
CurrentValue := EmailingListArray[1][CurrentPointer];
CurrentValue2 := EmailingListArray[2][CurrentPointer];
Pointer := CurrentPointer + 1;
while ((EmailingListArray[1][Pointer] > CurrentValue) AND (Pointer > 0)) do
begin
EmailingListArray[1][Pointer+1] := EmailingListArray[1][Pointer];
EmailingListArray[2][Pointer+1] := EmailingListArray[2][Pointer];
pointer := Pointer -1;
end;
EmailingListArray[1][Pointer + 1] := CurrentValue;
EmailingListArray[2][Pointer + 1] := CurrentValue;
end;
//show message at the end for a check
ShowMessage('hello?');
The message "hello?" isn't being displayed for some reason :S.
The program isn't crashing or anything so it really should atleast display "hello?" at the end.
It isn't sorting my arrays either.
Neither am I sure if the algorithm is written correctly, I got it out of our textbook.
Any help would be much appreciated!
If you want to get a good mark:
Avoid giving misleading names for your variables:
CurrentPointer should be called CurrentIndex or CurrentPosition as it is an index and not a Pointer
Pointer is to be avoided (reserved for Pointer type) and more so because it is not a Pointer; should be WorkIndex or WorkPosition
Read the Insertion sort algorithm (wikipedia has a simple pseudocode for array indexed from 0) and implement it properly:
WorkIndex := CurrentIndex - 1; // - not + in your "Pointer := CurrentPointer + 1;"
Get your Index range from 0 to Count-1 for a TStrings.
Don't mix up the 2 arrays:
EmailingListArray[2][WorkIndex + 1] := CurrentValue2; // not CurrentValue
Update: Missed the bad while condition for zero based array.
2bis. While condition should be with >=0, not >0
while ((EmailingListArray[1][WorkIndex] > CurrentValue) AND (WorkIndex >= 0)) do

Delphi library for MIDI input/output?

What is a good Delphi library for MIDI input/output?
Are you sure that you really need a third-party library? If your needs are basic, the Windows API is all you need (using MMSystem).
var
mo: HMIDIOUT;
const
MIDI_NOTE_ON = $90;
MIDI_NOTE_OFF = $80;
MIDI_CHANGE_INSTRUMENT = $C0;
MIDI_DEVICE = 0;
MIDI_VEL = 108;
procedure MIDIInit;
begin
midiOutOpen(#mo, MIDI_DEVICE, 0, 0, CALLBACK_NULL);
SetPlaybackVolume($FFFFFFFF);
end;
function MIDIEncodeMessage(Msg, Param1, Param2: integer): integer;
begin
result := Msg + (Param1 shl 8) + (Param2 shl 16);
end;
procedure SetCurrentInstrument(CurrentInstrument: TMIDIInstrument);
begin
midiOutShortMsg(mo, MIDIEncodeMessage(MIDI_CHANGE_INSTRUMENT, ord(CurrentInstrument), 0));
end;
procedure NoteOn(NewNote, NewIntensity: byte);
begin
midiOutShortMsg(mo, MIDIEncodeMessage(MIDI_NOTE_ON, NewNote, NewIntensity));
end;
procedure NoteOff(NewNote, NewIntensity: byte);
begin
midiOutShortMsg(mo, MIDIEncodeMessage(MIDI_NOTE_OFF, NewNote, NewIntensity));
end;
procedure SetPlaybackVolume(PlaybackVolume: cardinal);
begin
midiOutSetVolume(mo, PlaybackVolume);
end;
where the instruments are
type
TMIDIInstrument = (midiAcousticGrandPiano, midiBrightAcousticPiano,
midiElectricGrandPiano, midiHonkyTonkPiano,
midiRhodesPiano, midiChorusedPiano, midiHarpsichord,
midiClavinet, midiCelesta, midiGlockenspiel,
midiMusicBox, midiVibraphone, midiMarimba, midiXylophone,
midiTubularBells, midiDulcimer, midiHammondOrgan,
midiPercussiveOrgan, midiRockOrgan, midiChurchOrgan,
midiReedOrgan, midiAccordion, midiHarmonica,
midiTangoAccordion, midiAcousticGuitarNylon,
midiAcousticGuitarSteel, midiElectricGuitarJazz,
midiElectricGuitarClean, midiElectricGuitarMuted,
midiOverdrivenGuitar, midiDistortionGuitar,
midiGuitarHarmonics, midiAcousticBass, midiElectricBassFinger,
midiElectricBassPick, midiFretlessBass, midiSlapBass1,
midiSlapBass2, midiSynthBass1, midiSynthBass2, midiViolin,
midiViola, midiCello, midiContrabass, midiTremoloStrings,
midiPizzicatoStrings, midiOrchestralHarp, midiTimpani,
midiStringEnsemble1, midiStringEnsemble2, midiSynthStrings1,
midiSynthStrings2, midiChoirAahs, midiVoiceOohs,
midiSynthVoice, midiOrchestraHit, midiTrumpet, midiTrombone,
midiTuba, midiMutedTrumpet, midiFrenchHorn, midiBrassSection,
midiSynthBrass1, midiSynthBrass2, midiSopranoSax, midiAltoSax,
midiTenorSax, midiBaritoneSax, midiOboe, midiEnglishHorn,
midiBassoon, midiClarinet, midiPiccolo, midiFlute,
midiRecorder, midiPanFlute, midiBottleBlow, midiShakuhachi,
midiWhistle, midiOcarina, midiLead1Square,
midiLead2Sawtooth, midiLead3CalliopeLead, midiLead4ChiffLead,
midiLead5Charang, midiLead6Voice, midiLead7Fifths,
midiLead8BrassLead, midiPad1NewAge, midiPad2Warm,
midiPad3Polysynth, midiPad4Choir, midiPad5Bowed,
midiPad6Metallic, midiPad7Halo, midiPad8Sweep, midiEmpty0,
midiEmpty1, midiEmpty2, midiEmpty3, midiEmpty4, midiEmpty5,
midiEmpty6, midiEmpty7, midiEmpty8, midiEmpty9, midiEmpty10,
midiEmpty11, midiEmpty12, midiEmpty13, midiEmpty14,
midiEmpty15, midiEmpty16, midiEmpty17, midiEmpty18,
midiEmpty19, midiEmpty20, midiEmpty21, midiEmpty22,
midiEmpty23, midiGuitarFretNoise, midiBreathNoise,
midiSeashore, midiBirdTweet, midiTelephoneRing,
midiHelicopter, midiApplause, midiGunshot);
Try this:
procedure TForm1.FormCreate(Sender: TObject);
begin
MIDIInit;
SetCurrentInstrument(midiHarmonica);
NoteOn(50, 127);
sleep(200);
NoteOn(60, 127);
sleep(200);
NoteOn(70, 127);
sleep(200);
NoteOff(70, 127);
NoteOff(60, 127);
NoteOff(50, 127);
SetCurrentInstrument(midiAcousticGrandPiano);
NoteOn(70, 127);
NoteOn(80, 127);
sleep(1000);
SetCurrentInstrument(midiApplause);
NoteOn(64, 127);
sleep(2000);
NoteOff(64, 127);
end;
I've been using these components for ages:
http://bitbucket.org/h4ndy/midiio-dev
They've hardly ever failed on me, and unlike many other specialized Delphi components that have been around for this long, this code is pretty much alive (updates and improvements added recently).
Nothing fancy, but it's easy to use, fast, and rock solid. If you plan to do serious midi stuff, you'll eventually end up using this.
I've used these components for over 6 months now with great success. They should be evaluated with all the others in the follow up posts.
http://sourceforge.net/projects/midisequencer/
I have used BASS MIDI using the .NET wrapper with great success, and there are Delphi wrappers available for it too.
A very simple MIDI in/out class:
www.midimountain.com/delphi_midi.html
It looks like a good starting point if you would like to roll your own and use the windows API.
Just a small extra info: The SourceForge "dmidi" project is actually the same as the "midiio" on BitBucket (but the development happens here).
DMIDI project webpage
Mon 4/14/2014 9:49 am. Since I'm not allowed to comment, I'll try answering: I cast my living-in-the-past vote for the midimountain.com candidate. I got the demo_MidiDevices_D6.zip (get it on the page http://www.midimountain.com/delphi_midi.html, not the "download" link), unzipped it, and it compiled without incident in my antique Delphi 7 and ran. I haven't actually tested if it does MIDI, but it did show my menagerie of attached MIDI devices....

Resources