My copy code:
if OpenClipboard(mainwnd.Handle) then
MemHandle := GlobalAlloc(GHND or GMEM_SHARE, Succ(StrLen(pLclCopies)));
if MemHandle <> 0 Then
Begin
try
StrCopy(GlobalLock(MemHandle), pLclCopies);
GlobalUnlock(MemHandle);
SetClipboardData(cf_LocalVar,MemHandle);
Finally
CloseClipboard;
GlobalFree(MemHandle);
end;
end;
and my paste code:
if clipboard.HasFormat(cf_LocalVar) then
begin
ClipBoard.Open;
try
MyHandle := Clipboard.GetAsHandle(cf_LocalVar);
LocalsTextPtr := GlobalLock(MyHandle);
CheckForCopiedLocals(LocalsTextPtr, TextPtr); //What I do with the pasted data.
GlobalUnLock(MyHandle);
finally
Clipboard.Close;
end;
end;
My goal is to copy not only text from a special editor in my program, but also to copy some underlying variable data related to that editor. Most everything seems to be working fine clipboard wise - I'm seeing my copied text, and the 'cf_LocalVar' format appear in the ClipBook viewer on windows.
It's when I get to the paste side and the line
LocalsTextPtr := GlobalLock(MyHandle); doesn't get the copied data from the first bit of code. I see that it makes it into pLclCopies but then can't be sure that it's stored in the clipboard.
NB I have left out emptyclipboard from my code as this would get rid of the cf_text that I need along with the cf_LocalVar.
Related
Hi I'm currently using Delphi 2010.
I basically have a form where a user has to enter information about themselves and upload a picture. I have an Image component on my form. I did some research and many of the websites I looked at said to use a OpenPictureDialogue to allow the user to select an image and display it in the Image component.
My question is, how can I save this image to a file on my computer? Keeping in mind I will have multiple users adding their picture and that I will have to use the picture later on again, basically I want to use the LoadFromFile procedure to display the picture in my program later on.
I also read many websites saying to use the SavePictureDialogue, but that allows the user to select the file they want the image to be saved to and I don't want that, I want it to save to a file that only I can access.
I have this so far, I know it is very limited.
if opdAcc.Execute then
begin
if opdAcc.FileName <> '' then
begin
imgAccImage.Picture.LoadFromFile(opdAcc.FileName);
end;
end;
I am a student and my knowledge is quite limited and I would appreciate any help. :)
First of all, there is no place on the hard drive that only you can access. But you can create a folder to store your files and copy users' pictures there. This reduces the likelihood that the user will have access to these files. The usual folder for storing such files is the AppData folder. It is better to create a folder with the same name as your application in AppData and store such files there.
Suppose the GetPicturesDirectoryPath function generates the address of such a folder and ensures that this folder has already been created or will be created. The next step is to generate a unique name for the file you want to store. Note that multiple users may select files with the same name. In this case, after copying the picture selected by the second user, the image file will be written over the previous user's file. If a unique identifier is assigned to each user, this identifier is the best choice for the picture file name. But you can use the GetGUIDFileName function to create a unique address. Make sure the generated address is kept with the rest of the user information, or the connection between the copied file and the user will be lost. The implementation of all these will be something like the following:
uses IOUtils;
function GetAppDataDirectoryPath: string;
begin
...
end;
function GetPicturesDirectoryPath: string;
begin
Result := TPath.Combine(GetAppDataDirectoryPath, 'MyApp');
TDirectory.CreateDirectory(Result);
end;
function GetUniqueFilePath(const Extension: string): string;
begin
Result := TPath.ChangeExtension(
TPath.Combine(GetPicturesDirectoryPath, TPath.GetGUIDFileName),
Extension);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
DestPath: string;
begin
OpenPictureDialog1.Options := OpenPictureDialog1.Options +
[ofFileMustExist]; // make sure that selected file exists
if OpenPictureDialog1.Execute then
begin
DestPath := GetUniqueFilePath(TPath.GetExtension(OpenPictureDialog1.FileName));
TFile.Copy(OpenPictureDialog1.FileName, DestPath);
if TFile.Exists(DestPath) then
Image1.Picture.LoadFromFile(DestPath)
else
ShowMessage('Well, something went wrong!');
end;
end;
Read this to implement GetAppDataDirectoryPath.
I'm trying to load an image into a stringgrid cell
if CheckBox5.Checked = True then
begin
Ver := Ver + 1;
Bitmap := TBitmap.Create;
Bitmap.LoadFromFile('media/belgie_vlag.bmp');
Form3.StringGrid1.Canvas.StretchDraw
(Form3.StringGrid1.CellRect(Hor,Ver),Bitmap);
Bitmap.Free;
end;
When I run the application, an error shows saying the .bmp file cant be opened. Any help?
The most likely problem is that the file cannot be found, because you didn't specify an absolute path. You should always use absolute paths (e.g., C:\Users\Andreas Rejbrand\Desktop\image.png, not image.png).
For instance, if the media folder is a sibling to the executable file, the absolute path is ExtractFilePath(Application.ExeName) + 'media\belgie_vlag.bmp'.
The following code should then work:
if CheckBox5.Checked then
begin
Ver := Ver + 1;
Bitmap := TBitmap.Create;
try
Bitmap.LoadFromFile(ExtractFilePath(Application.ExeName) + 'media\belgie_vlag.bmp');
Form3.StringGrid1.Canvas.StretchDraw
(Form3.StringGrid1.CellRect(Hor,Ver),Bitmap);
finally
Bitmap.Free;
end;
end;
Notice a few more things:
You must always protect resources with try..finally blocks, as above. Otherwise, in this case, if an exception is raised when you load or draw the image, you will leak the image object, making your application eat memory and get a limited lifetime.
There is no need to write if mybool = True then; if mybool then is enough.
You should only draw in the string grid in the appropriate event handler. I cannot tell where your code is placed, so I don't know if you are doing it the right way or not.
I have developed a mp3 player with Delphi (XE) using the BASS library.
Due to certain reasons, I want to remove the BASS libraries and want to use the TMediaPlayer component in Delphi (also want to "move" the project to Delphi 10 Seattle).
Now I found out that some of my mp3 files have a "strange" jpg image embedded.
Means, that the Delphi components run into an error due to the image.
With long time debugging I can say the following:
try
mplMain.FileName := CurrentSong;
progbSong.Max := mplMain.Duration;
lblDuration.Text := DurationToString(mplMain.Duration);
PlayClick(Self);
except
on E: Exception do
begin
FMX.Dialogs.MessageDlg('Cannot play song: ' + CurrentSong + #10 + #13 +
'Reason: ' + E.Message,
TMsgDlgType.mtWarning, [TMsgDlgBtn.mbOK], 0,
procedure(const AResult: TModalResult)
begin
MediaNext;
end
);
end;
end;
This line:
mplMain.FileName := CurrentSong;
causes the problem.
Diving deeper in debugging it comes to here:
FMX.Media library:
procedure TMediaPlayer.SetFilename(const Value: String);
...
FMedia := TMediaCodecManager.CreateFromFile(FFileName);
...
At the end it ends up in FMX.Media.Win:
constructor TWindowsMedia.Create(const AFileName: string);
...
HR := FGraphBuilder.RenderFile(PChar(AFileName), nil);
...
When the line
HR := FGraphBuilder.RenderFile(PChar(AFileName), nil);
is called, in debug mode, the program just returns to the IDE.
In runtime mode, nothing happens. No error message, just "nothing".
As you can see, I wrapped the related line into a try...except block, but no error is raised. The program/player doesn't continue.
That's very bad for me, because I wanted to catch this "special case" and log the affected mp3 files to a logfile so that I can change the embedded image.
I found out that it is only caused by some images. Maybe they are "somehow corrupt", but shown in all other players.
When I remove the image and embed a "new" one and save the file, everything is fine and the TMediaPlayer can play the file.
How can I catch this certain kind of "error" to get the list of affected files?
I got it managed now.
Only in debug mode the application/player is exited without any thrown error and I find myself back in the IDE.
During runtime the try...except block works, when I chose an "affected file" manually. For the case that one file is played ("good one") and the next file is a "bad one", I had to change my "MediaNext" procedure. In this procedure I also had a try...except block when the filename was associated to the TMediaPlayer, but I just had set a bool variable for further use and didn't "jump" to the next file.
The code just was:
try
mplMain.FileName := CurrentSong;
except
on E:Exception do
SongNotPlayable := true;
end;
Here I can implement a routine to log the affected mp3 files into a logfile and then jump to the next file (if exists). :-)
Thanks again to all!
My program exits with RunError(5), which would suggest that it can't access the file, which it should be able to. I have checked and the file is used as it should be, the file isn't read-only, etc. What the program does is, it creates a .dat file if one doesn't exists and uses it for saving stuff. If I run the program and the file doesn't exist, the file is created, but after that, in the same execution, the program won't access the file. This ONLY happens if the file was created in the current execution.
This is the way in which the procedures are called(the code is quite long but I am giving you the first few lines, where the error occurs):
fileName := 'labSave.dat';
CreateFile;
assign(labyrinthFile,fileName);
writeln(CheckFileSize);
and then there is each of the procedures:
procedure Initialize;
begin
fileName := 'labSave.dat';
assign(labyrinthFile,fileName);
end;
procedure CreateFile;
begin
if not FileExists(fileName) then FileCreate(fileName);
end;
function CheckFileSize: integer;
begin
reset(labyrinthFile);
CheckFileSize := FileSize(labyrinthFile);
close(labyrinthFile);
end;
According to Lazarus forum (http://forum.lazarus.freepascal.org/index.php?topic=4936.0):
Runtime Error 5 means Access denied. The file maybe readonly and you
use the wrong (default) filemode, or you try to re-open the file with
a new filehandle without having closed it before (somewhere in the
while and repeat loops possibly you assignfile more then once, then
the reset fails?).
If I recall correctly now, the workflow should be as follows for create:
AssignFile(f, filename); Rewrite(f); CloseFile(f);
and for existing file:
AssignFile(f, filename); Reset(f); CloseFile(f);
Seeing other mistakes found in your code through questions in comments, I strongly suggest you to devote more time to debugging and when such errors happen - strip out ALL of the irrelevant code and check your code design for cases like above (assigning file before creating it, etc.).
I was trying to make a little test program to count how many times letter 'a' appears in an text without using string type:
program PascalTest;
uses WinCrt;
var
a:integer;
ch:char;
begin
a:=0;
writeln('Input text: ');
read(ch);
while ch <>'.' do // '.' marking the end of text ("eoln" could've been used instead)//
begin
case ch of
'A','a':a:=a+1;
end;
read(ch);
end;
writeln(a);
readln;
readln; //forcing output window to stay open//
end.
I noticed that if I dont add another 'readln' statement at the end , the output window will not show results (it will flash in an instant if u will).This is happening only with this program.All the other ones require only one 'readln' so the window can stay open. Can somebody explain to me why is another 'readln' statement needed in this case?
The first readln ends the while loop. Note that you can enter many '.' without loop exit. Further note the writeln(a) is delayed until you press <Enter>. The second readln allows you to view the output.
Make a test: Uncomment both readln and see if you can end the program by entering a '.'.
WinCrt is a consoleless CRT to use in combination with unit GRAPH.
Use unit Crt for normal console output.