-
Content Count
135 -
Joined
-
Last visited
-
Days Won
1
Everything posted by rvk
-
See my previous post, because I already got this working.
-
Yes, there are... (although I could also appreciate the comment of FredS ) I have it working here in 64 bit. Besides the INVALID_HANDLE_VALUE I mentioned earlier, you need to use the correct GetMsgProc() definition. The one now used is only valid in 32 bit. If you change it into this it worked here (both in the implementation and interface part). (although you might want to avoid a parameter named wParam because it is also a type in the Windows unit which you need, solved here with unit-prefixing)
-
Yep. That was my conclusion too. There still must be something wrong. Using WH_CBT you do get some messages. There supposed to be a HCBT_SYSCOMMAND message containing the information but I haven't looked at it further.
-
The reason for this is because GetMsgProcRec seems to be nil in the DLL. It seems that the call to CreateFileMapping fails in 64 bit. For testing this you can add your fwGetMsgProc dll project to the projectgroup of TESTHks and debug the dll-calls. Set a breakpoint in InitializeDll and you'll see it stops at the first MappedMem line. Next (on the second try) trace into the procedure with F7 and you'll see the exception for cErrorCreating,['TMappedMem'] is called. You'll see a $FFFFFFFF as parameter, meaning an invalid handle (see https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createfilemappinga) But INVALID_HANDLE_VALUE is THandle(-1) which is something different then $FFFFFFFF in 64 bit. (you'll need $FFFFFFFFFFFFFFFF) So change it to Now the hook can successfully be installed. (I hadn't much luck with catching anything but now you're a step closer )
-
I don't think 'injecting code' is the best way to go. I think you need to catch the WM_SYSCOMMAND which is sent to the other application(s). You should be able to do that with SetWindowsHookEx(). https://social.msdn.microsoft.com/Forums/windows/en-US/f87193b7-ccc2-4c30-9b1e-195addd375c8/how-to-intercept-a-wmsyscommand-sent-to-another-app?forum=winforms An example in C++ http://forums.codeguru.com/showthread.php?161054-System-wide-hook-for-WM_SYSCOMMAND
-
Zero cost, fully automated secure off-site database backup (FireBird 3.0.4)
rvk replied to Yaron's topic in Databases
Ah, Ok. I wanted my backup script to make transportable backups. nbackup doesn't do that (but is faster because of it). Because speed isn't an issue (because both can backup a database while in use and I only make daily backups, not hourly) I went for gbak. https://firebirdsql.org/manual/nbackup-overview.html -
Zero cost, fully automated secure off-site database backup (FireBird 3.0.4)
rvk replied to Yaron's topic in Databases
I did something similar with gbak i.c.w. nextcloud and the task scheduler (inside a cmd-script). Any reason to prefer nbackup above gbak? -
is there any "currency to words" routine for Delphi?
rvk replied to Attila Kovacs's topic in Algorithms, Data Structures and Class Design
Correct. The base of the code from NumWords is just 70-somewhat lines and can easily be adjusted to follow the additional/proper rules. const Digits: array [1 .. 9] of string = ( 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'); Teens: array [1 .. 9] of string = ( 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'); TenTimes: array [1 .. 9] of string = ( 'ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'); function DoTriplet(TheNumber: Integer): string; var Digit, Num: Integer; begin Result := ''; Num := TheNumber mod 100; if (Num > 10) and (Num < 20) then begin Result := Teens[Num - 10]; Num := TheNumber div 100; end else begin Num := TheNumber; Digit := Num mod 10; Num := Num div 10; if Digit > 0 then Result := Digits[Digit]; Digit := Num mod 10; Num := Num div 10; if Digit > 0 then Result := TenTimes[Digit] + ' ' + Result; Result := Trim(Result); end; Digit := Num mod 10; if (Result <> '') and (Digit > 0) then Result := 'and ' + Result; if Digit > 0 then Result := Digits[Digit] + ' hundred ' + Result; Result := Trim(Result); end; function NumberInWords(TheNumber: Integer): string; var Num, Triplet, Pass: Integer; begin if TheNumber < 0 then Result := 'Minus ' + NumberInWords(-TheNumber) else begin Result := ''; Num := TheNumber; if Num > 999999999 then raise Exception.Create('Can''t express more than 999,999,999 in words'); for Pass := 1 to 3 do begin Triplet := Num mod 1000; Num := Num div 1000; if Triplet > 0 then begin if (Pass > 1) and (Result <> '') then Result := ', ' + Result; case Pass of 2: Result := ' thousand' + Result; 3: Result := ' million' + Result; end; Result := Trim(DoTriplet(Triplet) + Result); end; end; end; end; procedure TForm1.FormCreate(Sender: TObject); begin Showmessage(NumberInWords(2120229)); end; -
is there any "currency to words" routine for Delphi?
rvk replied to Attila Kovacs's topic in Algorithms, Data Structures and Class Design
You mentioned a "great solution on a website". https://www.calculator.org/calculate-online/mathematics/text-number.html It translates 2019 to "two thousand, nineteen" How does that one follow those rules? But maybe there are better ones. But I haven't even seen any ones online that convert according to those rules. (or maybe this one https://www.tools4noobs.com/online_tools/number_spell_words/) -
is there any "currency to words" routine for Delphi?
rvk replied to Attila Kovacs's topic in Algorithms, Data Structures and Class Design
And what doesn't satisfy you with the NumWords v.4.6 result? (Worked fine for me) -
is there any "currency to words" routine for Delphi?
rvk replied to Attila Kovacs's topic in Algorithms, Data Structures and Class Design
Something like this? https://torry.net/quicksearchd.php?String=numwords&Title=Yes It would be useful if you mentioned which ones didn't satisfy you because now you could get duplicate suggestions. -
Looking at the source, each time you press the OK button a private variable FAttempt is increased. When it goes over the AttemptNumber a Cancel is automatically triggered. So the Login will fail. procedure TJvLoginForm.OkBtnClick(Sender: TObject); begin Inc(FAttempt); if Assigned(FOnOkClick) then FOnOkClick(Self) else ModalResult := mrOk; if (ModalResult <> mrOk) and (FAttempt >= AttemptNumber) then ModalResult := mrCancel; end;
-
That depends on where you put the TJvLoginDialog. If you have a DataModule, ideally the TJvLoginDialog goes on the TDataModule and you'll execute it in the DataModuleCreate() after connecting to the TDatabase. Set Active to false at designtime so you can do this yourself in the DataModuleCreate(). Login.Active := true; if not Login.Execute then begin // inform the user and exit Application.Terminate; end; In the OnCheckUser you can check the database if the user has entered valid credentials. If you have the TDatabase component on a TForm and you initialize it there, then you'll need to put the TJvLoginDialog there too (in FormCreate() and after the initialization of the TDatabase-component).
-
Like I stated before, you can do it with Synapse (from Ararat) and libssh2.dll. There is a SimpleSFTP.pas in the demo-directory. But that one uses cryptlib.dll which isn't free distributable. But there are version which can also use libssh2.dll (which is free). I have one for FPC but not ported to Delphi. There are also versions which use plain winsock in combination with libssh2.dll (no need for Synapse). For example: https://github.com/pult/libssh2_delphi (and like others on github) Using the searchwords libssh2 and delphi in Google will get you a lot of results too. For the Synapse version you can just search for SimpleSFTP.pas and libssh2 and you can search for the latest working with libssh2.dll. If you have any problems let us know.
-
You can do it with Synapse in combination with cryptlib, or better libssh2.dll, for free. There is some source out there (I think sftp_2000) for Delphi. If you can't find it I could convert the example I have from FPC/Lazarus back to Delphi (will need some time for that).
-
You can use TWebBrowser.WebBrowser1DocumentComplete() and read out WebBrowser1.Document.documentElement.outerHTML; (like discussed above) You can strip out any script tags and html tags and you end up with the plain text. (you should add line breaks on div en br tags though otherwise you have text on one line.) Or you might look for HTML2TEXT function which does all that work for you. But the readable text is there in the .outerHTML.
-
You might want to dial down the sarcasme. I'm trying to help you here and with that attitude I'm feeling less and less inclined to do so. With my example I retrieved your search result and got this (this is a snippet just to show you the content is there). <div class="I6vAHd h5RoYd ads-creative">Dr. Lazer is a <b>Baltimore Dentist</b> Dedicated To Quality <b>Dental</b> Care. Financing Available. Patient Focused <b>Dentistry</b>. Top <b>Baltimore Dentists</b>. Advanced Training. Services: Cosmetic <b>dentistry</b>, General <b>dentistry</b>, Porcelain veneers, Teeth whitening, <b>Dental</b> implants, Cosmetic dentures, <b>Dental</b> crowns.</div><ul class="OkkX2d"><li><a class="V0MxL" onmousedown="return google.f[this.getAttribute('data-mousedown')](this)" ontouchstart="return google.f[this.getAttribute('data-touchstart')](this)" href="https://www.cosmeticdentistbaltimore.com/our-office/ed-lazer-dds/?TrackNum=410-753-2005" data-ved="2ahUKEwj7o4KsiIPkAhVEJlAKHYQZDhMQpigoAHoECA8QBA" data-touchstart="bez1fd" data-mousedown="LmvwCb" data-arwt="//www.googleadservices.com/pagead/aclk?sa=L&ai=DChcSEwia64isiIPkAhVH5HcKHQCGCzoYABABGgJlZg&ohost=www.google.com&cid=CAASE-RoDCdUQXMX66yba6ZIKqfKGC0&sig=AOD64_0RkT0b2u8xR9l7_LEQw9VUouKjzQ&adurl=&rct=j&q=">Meet Dr. Ed Lazer</a></li><li><a class="V0MxL" onmousedown="return google.f[this.getAttribute('data-mousedown')](this)" ontouchstart="return google.f[this.getAttribute('data-touchstart')](this)" href="https://www.cosmeticdentistbaltimore.com/for-patients/special-offers/?TrackNum=410-753-2005" data-ved="2ahUKEwj7o4KsiIPkAhVEJlAKHYQZDhMQpigoAXoECA8QBQ" data-touchstart="bez1fd" data-mousedown="LmvwCb" data-arwt="//www.googleadservices.com/pagead/aclk?sa=L&ai=DChcSEwia64isiIPkAhVH5HcKHQCGCzoYABACGgJlZg&ohost=www.google.com&cid=CAASE-RoDCdUQXMX66yba6ZIKqfKGC0&sig=AOD64_2gU3L1cLsoIxMZDy60AJIwH1-G4w&adurl=&rct=j&q=">Special Offers</a></li><li><a class="V0MxL" onmousedown="return google.f[this.getAttribute('data-mousedown')](this)" ontouchstart="return google.f[this.getAttribute('data-touchstart')](this)" href="https://www.cosmeticdentistbaltimore.com/smile-gallery/?TrackNum=410-753-2005" data-ved="2ahUKEwj7o4KsiIPkAhVEJlAKHYQZDhMQpigoAnoECA8QBg" data-touchstart="bez1fd" data-mousedown="LmvwCb" data-arwt="//www.googleadservices.com/pagead/aclk?sa=L&ai=DChcSEwia64isiIPkAhVH5HcKHQCGCzoYABADGgJlZg&ohost=www.google.com&cid=CAASE-RoDCdUQXMX66yba6ZIKqfKGC0&sig=AOD64_0Eq9nb4XnF90RRE1Ik35kT7kFBQQ&adurl=&rct=j&q=">Smile Gallery</a></li><li><a class="V0MxL" onmousedown="return google.f[this.getAttribute('data-mousedown')](this)" ontouchstart="return google.f[this.getAttribute('data-touchstart')](this)" href="https://www.cosmeticdentistbaltimore.com/request-appointment/?TrackNum=410-753-2005" data-ved="2ahUKEwj7o4KsiIPkAhVEJlAKHYQZDhMQpigoA3oECA8QBw" data-touchstart="bez1fd" data-mousedown="LmvwCb" data-arwt="//www.googleadservices.com/pagead/aclk?sa=L&ai=DChcSEwia64isiIPkAhVH5HcKHQCGCzoYABAEGgJlZg&ohost=www.google.com&cid=CAASE-RoDCdUQXMX66yba6ZIKqfKGC0&sig=AOD64_2N4qM3fV1hZgFsH22ko3zEIjVzFQ&adurl=&rct=j&q=">Schedule Appointment</a></li><li><a class="V0MxL" onmousedown="return google.f[this.getAttribute('data-mousedown')](this)" ontouchstart="return google.f[this.getAttribute('data-touchstart')](this)" href="https://www.cosmeticdentistbaltimore.com/contact/?TrackNum=410-753-2005" data-ved="2ahUKEwj7o4KsiIPkAhVEJlAKHYQZDhMQpigoBHoECA8QCA" data-touchstart="bez1fd" data-mousedown="LmvwCb" data-arwt="//www.googleadservices.com/pagead/aclk?sa=L&ai=DChcSEwia64isiIPkAhVH5HcKHQCGCzoYABAFGgJlZg&ohost=www.google.com&cid=CAASE-RoDCdUQXMX66yba6ZIKqfKGC0&sig=AOD64_0sMvnrhd-h49qKlc3LKos0K2h67w&adurl=&rct=j&q=">Contact Us</a></li></ul></li><li class="ads-ad" data-hveid="CBAQAA" data-bg="1"><div class="ad_cclk"><a id="n1s0p2c0" style="display: none;" href="https://www.googleadservices.com/pagead/aclk?sa=L&ai=DChcSEwia64isiIPkAhVH5HcKHQCGCzoYABAGGgJlZg&ohost=www.google.com&cid=CAASE-RoDCdUQXMX66yba6ZIKqfKGC0&sig=AOD64_38aJbvxP_v7qoqtk0s9Byp6f8NQw&rct=j&q=&ved=2ahUKEwj7o4KsiIPkAhVEJlAKHYQZDhMQ0Qx6BAgQEAE&adurl="></a><a class="V0MxL r-ieStqovnU5rk" id="vn1s0p2c0" onmousedown="return google.arwt(this)" ontouchstart="return google.arwt(this)" href="https://www.aspendental.com/dentist/md/dundalk/1401-merritt-blvd" jsl="$t t-r1glFWqNI5A;$x 0;"><h3 class="sA5rQ">Official Aspen Dental | Affordable dentistry</h3><br><div class="ads-visurl"> You see that text: Dr. Lazer is a <b>Baltimore Dentist</b> Dedicated To Quality <b>Dental</b> Care. Financing Available. Is that what you are after? (this is from the outerHTML) Yes, it's riddled with javascript and lots of tags. But it's valid HTML with the content provided on screen of the user. If it's not, please provide some text that you did expect. BTW, You do need to read out outerHTML in WebBrowser1DocumentComplete() because the javascript needs time to run. But I assumed you already knew this.
-
Why should I try it???? But alright... I tried and it works. With this source file Test <div id=content> Some other content </div> <script type = "text/JavaScript"> document.getElementById("content").innerHTML = "Changed content"; </script> I got this in Delphi for var d: OleVariant; begin d := WebBrowser1.Document; Memo1.Lines.Text := d.documentElement.outerHTML; end; <HTML><HEAD></HEAD> <BODY>Test <DIV id=content>Changed content</DIV> <SCRIPT type=text/JavaScript> document.getElementById("content").innerHTML = "Changed content"; </SCRIPT> </BODY></HTML> Note the "Changed content" between the divs of id=content !! The javascript itself obviously stays there because it's part of the source but the content itself is the way it is represented to the end-user after executing the javascript. The DOM even places the missing HTML, HEAD and BODY tags in there.
-
Shouldn't this be possible with just TWebBrowser? Look at https://stackoverflow.com/a/22518562/1037511 So its seems like OuterHtml should give you the rendered HTML. Make sure to get this after the document is completed loading.
-
If you can put together an example and the virtual channels work the same on RDP on win10, I can take a look. I take it this should do the same as TSScan and RemoteDesktopTwain but then directly from your own local utility program.
-
Ah. But it does not not crap out There is definitely some alignment problem. You say "RDS" DLL. How is that DLL different? Is there something done with the calls? Could you share the code? Maybe if that problem is fixed, the other method with ttmNative is fixed automatically too.
-
Then there still could be some other type mismatches in there. Did you also try the TransferMode := ttmMemory; method already?
-
So the call gives a TWRC_XFERDONE (successful) but the handle could still be invalid. The handle (hNative) is a TW_UINT32 (which is a Cardinal/32bit). I wonder if it shouldn't be a TW_Handle (which should be a NativeUInt and UInt64 on 64 bit). At least GlobalLock expects a THandle (which is UInt64 on 64 bit). Doesn't seem really wise to stuff a handle in an Cardinal/32bit on 64 bit (which like David already mentioned, could be just a simple 32/64 bit truncation error). Strange this worked locally on the machine itself but fails on RDP. Maybe the handle-numbers are much larger and it fails.
-
Are your connecting client, the used mstsc.exe and RDP-session (including your app) ALL 64 bit? (If not, you can't rely on the Virtual Channel Client DLL) Did you check the numerical value of hNative (i.e. not being 0)?
-
So, the drivers are not loaded on the server itself? I'm not familiar with Virtual Channels in RDP, but I think this would mean you have the DLL on the local client and want the application, which runs on the server side in RDP, have access to the local scanner through the Virtual Channels-technology? Just like a Redirected Printer uses Virtual Channels. That's a whole lot of places where things can go wrong (that's why I asked if the scanner and drivers and DLL where locally on the server side in the RDP session itself). What was the value of the return-code on this line (in TTwainSource.TransferImages for TransferMode ttmNative): rc := Owner.TwainProc(AppInfo, @Structure, DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, @hNative); That seems to be where hNative gets its value (which fails). It seems the value is not checked for success there ( if rc <> TWRC_SUCCESS then ... should give error )