Thoughts from Dan Miser RSS 2.0
# Thursday, March 03, 2005
For those of you who use ActiveForms, you may have applied my technique to solve the problem when the ActiveX ActiveForm is not activated. Unfortunately, this one line of code gives us a new problem losing focus. For example, say you have focus on a button, and that button calls ShowMessage. If you did a PostMessage(WM_ACTIVATE), then you'll notice that the focus is lost after returning from the ShowMessage call. More precisely, the currently focused control at this point is the Shell DocObject View window used within IE. From this point on, pressing TAB will not take you from control to control within your ActiveForm. You can use the mouse to set focus, but that's sub-optimal.

To solve this, the easiest thing I found was to use the OnFrameWindowActivate and OnDocWindowActivate methods of the IOleInPlaceActiveObject interface. I posted another article about how to use a custom TActiveXControlClass, and that code already uses a method from IOleInPlaceActiveObject. This means that all we need to do is add these 2 methods to that existing class and implement them. The code looks like this:


type
  TTranslateAcceleratorFormControl = class(TActiveFormControl, IOleInPlaceActiveObject)
  private
    FActiveHWND: HWND;
    procedure HandleActiveHWND(Activate: boolean);
  protected
    function TranslateAccelerator(var msg: TMsg): HResult; stdcall;
    function OnFrameWindowActivate(fActivate: BOOL): HResult; stdcall;
    function OnDocWindowActivate(fActivate: BOOL): HResult; stdcall;
  end;


procedure TTranslateAcceleratorFormControl.HandleActiveHWND(Activate: boolean);
begin
  if Activate then
  begin
    if FActiveHWND <> 0 then
      SetFocus(FActiveHWND);
  end
  else
    FActiveHWND := GetFocus;
end;

function TTranslateAcceleratorFormControl.OnDocWindowActivate(fActivate: BOOL): HResult;
begin
  Result := inherited OnDocWindowActivate(fActivate);
  HandleActiveHWND(fActivate);
end;

function TTranslateAcceleratorFormControl.OnFrameWindowActivate(fActivate: BOOL): HResult;
begin
  Result := inherited OnFrameWindowActivate(fActivate);
  HandleActiveHWND(fActivate);
end;

function TTranslateAcceleratorFormControl.TranslateAccelerator(var msg: TMsg): HResult;
begin
  Result := inherited TranslateAccelerator(msg);

  if Result = S_OK then
  begin
    if (msg.message = WM_KEYDOWN) and (GetKeyState(VK_CONTROL) < 0) and (msg.wParam = 67) then
      Result := S_FALSE;
  end;
end;

If you test the ActiveForm at this point, you'll find that things work pretty well. The one remaining problem is that these methods don't fire when getting activated, so I handled that by adding another PostMessage after the PostMessage(WM_ACTIVATE) call. By doing this, we're letting the DAX framework set things up properly, and during that time, InPlaceActivate is called which finishes proper initialization. The code in the ActiveForm class looks similar to this:


type
  TMyActiveForm = class(TActiveForm, IMyActiveForm)
    procedure UMACtivate(var Message: TMessage); message UM_ACTIVATE; // const UM_ACTIVATE = WM_USER + 123;
// Other methods declared here

procedure TMyActiveForm.UMActivate(var Message: TMessage); 
begin
  (ComObject as IOleInPlaceActiveObject).OnFrameWindowActivate(true);
end;

Be sure to call

PostMessage(Handle, UM_ACTIVATE, 0, 0);
after your existing PostMessage call to WM_ACTIVATE.

Let me know if you run into any problems with this approach.

Thursday, March 03, 2005 1:19:00 PM (Central Standard Time, UTC-06:00)  #    Comments [1] -

# Friday, February 25, 2005
We currently use Multilizer in our product. However, we really don't use all of the features. It's use is pretty confined to "dynamically display messages" and "translate captions/labels on forms". Using Delphi 6 with Multilizer 5, things work fairly well.

We are also preparing the switch to Delphi 2005 in the next couple weeks. After contacting Multilizer, it turns out that there is no support for Multilizer 5 with Delphi 2005, and as a result, we would be required to spend many thousands of dollars to upgrade to Multilizer 6. That isn't a very attractive option. As of this writing, Multilizer will be thrown out of here, never to return. I'm investigating using Delphi's built-in Integrated Translation Environment (ITE) at the moment. I remember there were all sorts of problems with ITE early on (like in the Delphi 3/4 days). I'm hoping enough work has been done in this area to make it usable for our fairly simple needs. If not, we're writing our own tools to do this.

I believe component vendors should provide version compatible releases for newer versions of Delphi. Most component vendors actually do this quite well. I also believe that when companies try to force you into spending thousands of dollars, you should look to replace them immediately.

Friday, February 25, 2005 11:28:00 AM (Central Standard Time, UTC-06:00)  #    Comments [8] -
Delphi
# Tuesday, February 22, 2005
Using Mike Scott's old Netscape plugin SDK, I've been very successful in getting applications deployed with a variety of deployment options (thin client EXE, IE ActiveX/ActiveForm, and Netscape plugin). However, the Plugin SDK has been updated several times, and I haven't gone back to keep the original Delphi port up to date. Add to this mix the "other browsers" on the market that also need to be supported, and I was left wondering which direction to go.

The result was that I found the Netscape ActiveX plugin that allows ActiveX controls to be used inside Netscape-compatible browsers. So far, the results have been mixed, but I like the idea of having single-sourced code that compiles to the same deployment option (ActiveX), and let the browsers worry about how to handle it.

Tuesday, February 22, 2005 11:56:00 AM (Central Standard Time, UTC-06:00)  #    Comments [3] -
Delphi
# Monday, February 21, 2005
There are plenty of things that can be done to keep a developer from making repeatable and preventable mistakes. So the question really is: What kind of fines motivate developers? I look at fines as not only a deterrent but a way to help improve the talent of the entire development team and build team camaraderie. I've read that people at Microsoft that break the build take the build process until the next person breaks the build, but for me, nothing says "fine" like monetary punishment. ;-)

The fines listed below are not exactly going to break someone's pocket, but it does hurt to go into your wallet and pay up. The fines accumulate in a fine jar until there is enough to bring in doughnuts for the entire office.

So, what do you guys use for a fine system?

  • Making wild claims without having or providing supporting evidence: $1.00
  • Not writing a test case to isolate a bug: $2.00
  • Checking in code that doesn't compile (including hints/warnings, and active database connections at design-time): $2.00
  • Losing the IFDEFs in a DPR (typical when doing Add To Project in the IDE): $1.00 per DPR
  • Checking in code that causes users not to be able to run (typically done when not testing first): $1.00
  • Modifying editor options without prior approval: $1.00
Monday, February 21, 2005 3:05:00 PM (Central Standard Time, UTC-06:00)  #    Comments [5] -

# Friday, February 18, 2005
Some of you may remember my post on AQTime back in December. At the time, I commented that there were some show-stopper bugs that were preventing me from using AQTime (D6 run-time package and leaked Delphi object names not reporting correctly were the main ones).

I'm happy to report that my first reason for sticking with AQTime (Support) has proven to be a good read. Running AQTime 4.40.469.0, coupled with a custom patch acquired from their support department, I now have AQTime 4 working in my environment. I like the GUI better in AQTime 4, and the service support is tons better. For example, I couldn't profile a COM service properly in AQTime 3 (using SvCom), but it works just fine in AQTime 4.

I'm looking forward to identifying all sorts of wicked issues now. :-)

Friday, February 18, 2005 10:31:00 AM (Central Standard Time, UTC-06:00)  #    Comments [0] -
Delphi
# Monday, February 14, 2005
While I'm not exactly the first one to do so, I would like to throw my congratulations out there as well. I just listened to this interview about the creation of Delphi, and it definitely brought back memories.

At the time, I was working for Med Data Systems, Inc. out of San Diego in my first gig out of college. It was a great time of learning and finding out exactly what it meant to be a professional software developer. One of my tasks was to port our DOS codebase to a Windows application. Since we used Turbo Pascal for DOS since version 5.0, it seemed like a natural fit to stay with Borland. We looked at TPW and VB, but in the end, once we saw what Delphi was like, there was no need to look any further.

My boss, Steve Belkin, and myself ended up flying up to the launch event in San Francisco (try explaining to your girlfriend that you're heading up to San Francisco over Valentine's Day and see what kind of look you get :-)). It was every bit the event that you've heard it was. If anything, the reports don't do it justice. It was truly a once-in-a-lifetime experience to witness the event first-hand, from the initial technical session where we got free software, to watching the stampede of people on the floor clamoring for the trial copy. Not to mention, Borland throws the best parties in the industry, and this one was probably their finest ever. I do miss Cadillac Margaritas...

Monday, February 14, 2005 3:16:00 PM (Central Standard Time, UTC-06:00)  #    Comments [0] -
Delphi
# Wednesday, February 09, 2005
This is a quick followup on my post, HTTPSRVR with Apache. If you're using an older version of httpsrvr (e.g. from Delphi 6), then you need to add the following OnCreate/OnDestroy events for the main httpsrvr WebModule. The reason you need to do this is that each thread needs COM initialized, and Apache doesn't automatically do that initialization (whereas, IIS does).


procedure THTTPServer.WebModuleCreate(Sender: TObject);
begin
  { Each web module will be in a separate thread. We need to initialize
    the COM subsystem for each thread }
  if Assigned(ComObj.CoInitializeEx) then
    ComObj.CoInitializeEx(nil, COINIT_MULTITHREADED)
  else
    CoInitialize(nil);
end;

procedure THTTPServer.WebModuleDestroy(Sender: TObject);
begin
  CoUninitialize;
end;
Wednesday, February 09, 2005 11:20:00 AM (Central Standard Time, UTC-06:00)  #    Comments [0] -
Delphi
# Tuesday, February 08, 2005
I recently needed to get some simple XOR-type encryption. At first, I was led to TI2803 by Borland. However, that tech note has some problems with the strings having unprintable characters in it (specifically, #0 is troublesome when passing the string around).

I finally came across Peter Martin's solution, which solves all of my needs quite nicely.

Tuesday, February 08, 2005 9:55:00 AM (Central Standard Time, UTC-06:00)  #    Comments [2] -

Navigation
Archive
<March 2005>
SunMonTueWedThuFriSat
272812345
6789101112
13141516171819
20212223242526
272829303112
3456789
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2012
Dan Miser
Sign In
Statistics
Total Posts: 375
This Year: 3
This Month: 0
This Week: 0
Comments: 654
Themes
Pick a theme:
All Content © 2012, Dan Miser
DasBlog theme 'Business' created by Christoph De Baene (delarou)