Showing posts with label Tips. Show all posts
Showing posts with label Tips. Show all posts

Friday, June 3, 2011

Xcode Column Mode

Holding down the option key while dragging allows you to perform a column based selection of text.

Thursday, April 28, 2011

Remote Shutdown

Have you ever found yourself using Microsoft Remote Desktop without access to the physical machine and you need to reboot it? Or sometimes you have access to the physical machine but there isn't a keyboard hooked up for some bizarre reason that makes perfect sense to you. If so then you probably already know this and this post is pointless, but every so often I encounter someone that doesn't know the about shutdown.exe. Microsoft has a pretty old article about How To Use the Remote Shutdown Tool to Shut Down and Restart a Computer in Windows 2000. My use of shutdown.exe is to force a restart now:

c:\shutdown -t 00 -f -r

Thursday, October 15, 2009

Delphi Tips and Tricks - Additional Files

One of the most useful features in the Delphi IDE is CTRL + F12, or the "Search for units" dialog. One of the problems we encounter is we often want to look at files that are not in any of the opened projects. So a hidden registry key was created to add a list of files to the "Search for units" dialog. You can specify the text file by creating a string value under HKEY_CURRENT_USER\Software\CodeGear\BDS\\Globals named "AdditionalViewFiles". Set the string to the file you want the IDE to load. Note that IDE environment variables can be used here. For Example I have $(TP) set to "c:\source" and the AdditionalViewFiles string value is set to $(TP)\AdditionalViewFiles.txt.

The text file format is name value pairs like any other INI file where the name is the short name you want to see and the value is the full path to the file (and this will expand IDE environment variables as well). For example:

Foo.pas=$(TP)\somedirectory\Foo.pas

Tuesday, September 22, 2009

Delphi 2010 - Touch and Pen added to TShiftState

While we were researching adding Touch and Gesturing to VCL we quickly realized it was important to detect what type of input produced the mouse messages. So we introduced some new elements to TShiftState: ssTouch and ssPen:


TShiftState = set of (ssShift, ssAlt, ssCtrl,
ssLeft, ssRight, ssMiddle, ssDouble, ssTouch, ssPen);

One of the key reasons this is so important is when handling WM_TOUCH messages the mouse messages are also fired. Chances are you only want to handle one of them. On a non-touch machine you want to handle the mouse. So this allows input to be filtered and handled independently.

Thursday, April 2, 2009

Delphi Tips and Tricks: Quickly Switching Between Chunks of Code

I learned this trick from Chuck Jazdzewski so it's a goodie but oldie and real simple.

If you are working on two chunks of code that you need to go between you can use a comment like this:


{Exit(0); //}Exit(1);

Remove the first curly brace and instantly and easily your code changes:
  
Exit(0); //}Exit(1);

There is also a version of this for C++:

//*
return 0;
/*/
return 1;
//*/


Remove the first slash and instantly and easily your code changes:

/*
return 0;
/*/

return 1;
//*/

Tuesday, March 10, 2009

Delphi Performance Tip

Here's a small little Delphi performance tip that I'm not sure many people are aware of. Putting the $EXTERNALSYM after the symbol has better compiler performance than placing it before the symbol. The reason for this is pretty simple. When the compiler encounters a $EXTERNALSYM it looks for the symbol. If the symbol isn't found then it must be stored and dealt with later. If the symbol is found it is used immediately.

Here's a small example:


const
MAPVK_VK_TO_VSC = 0;
{$EXTERNALSYM MAPVK_VK_TO_VSC}
MAPVK_VSC_TO_VK = 1;
{$EXTERNALSYM MAPVK_VSC_TO_VK}
MAPVK_VK_TO_CHAR = 2;
{$EXTERNALSYM MAPVK_VK_TO_CHAR}
MAPVK_VSC_TO_VK_EX = 3;
{$EXTERNALSYM MAPVK_VSC_TO_VK_EX}
MAPVK_VK_TO_VSC_EX = 4;
{$EXTERNALSYM MAPVK_VK_TO_VSC_EX}

Friday, January 30, 2009

Delphi Object Inspector Tip of the Day

Did you know you can incremental search in the Object Inspector? Focus any item in the object inspector with your mouse or F11, press Tab the cursor will be brought to the name side of the object inspector, start typing, then press Tab again and the cursor will be back on the value side of the Object Inspector. Yeah, it probably should be more obvious.

Tuesday, September 23, 2008

Delphi 2009 - Unicode in Type Libraries

If you've opened up the Tools | Options in Delphi 2009 and taken a look at C++ Type Library Options and Delphi Type Library Options you'll notice the options are relatively the same as previous version but there are a few additions that might not be all that easy to understand. Here's a screen capture of the two dialogs:


Notice the two UTF8 options:

- Store Unicode data as UTF8 in type library
- Check for UTF8 data in type library

I'll explain what these do but first I we need a bit of a back story.

Back when the COM team was working on the new COM features for Tiburon (Delphi 2009 and C++ Builder 2009), we found that ICreateTypeLib, ICreateTypeLib2, ICreateTypeInfo and ICreateTypeInfo2 don't actually support BSTRs even thoough all their string paramters are BSTRs. Somewhere in the writing of the .tlb file the data is narrowed down and the unicode data is lost. After some testing using MIDL 5.01.0164 we found that Microsoft had apparently known about this and worked around it by UTF8 encoding the data and then stuffing it into the BSTR. Then we found that the latest version of MIDL 7.00.0500 produced errors when compiling files with unicode data.

So we wanted to support unicode throughout the product so we added support for UTF8 data in type libraries. The two options read UTF8 data and write UTF8 data. This means you can create unicode identifiers (functions and classes) for use between Delphi and C++Builder 2009 (and apparently MIDL 5.01.0164) but that's about it. I would suggest staying away from unicode identifiers in your Type Libraries.

Friday, September 19, 2008

Delphi and C++Builder 2009 - TApplication is Apartment Threaded

In Delphi 2009 and C++Builder 2009 (AKA Tiburon) by default the main thread of a VCL application will be apartment threaded. Take a look at TApplication.Create for the details. This isn't really a change from previous versions of VCL but the location of the call and how to override it is new. And now VCL calls OleInitialize instead of CoInitialize so there is a slight behavior change.

There may be reasons why a developer won't want this default behavior and the best way of doing this is to create this unit:

unit InitCom;

interface

implementation

uses
  ActiveX;

var
  NeedToUninitialize: Boolean;
initialization
  NeedToUninitialize := Succeeded(CoInitializeEx(nil, COINIT_MULTITHREADED));
finalization
  if NeedToUninitialize then
    CoUninitialize;
end.

And place it in the .dpr as the first unit (it must be before Forms or anything that brings in Controls).

It isn't recommended to run any UI under a multithreaded apartment but this will allow those who need it to change the default threading model.

Here is a blog post by Raymond Chen about why running the UI thread as multithreaded isn't a good idea.

Thursday, June 12, 2008

Delphi Tips and Tricks: Copy and Paste from the Type Library Editor

If you've used the type library editor in Delphi or C++Builder you've noticed that Cut, Copy and Paste don't work (CTRL + X, CTRL + C, CTRL + V). Well actually it's just Paste (CTRL + V) that doesn't work. To make a long story short the reason for this problem is due to the architecture of the IDE making it impractical to get this to function. The good news is there is actually a shortcut for Paste. So instead of CTRL + V, use Shift + Insert.

Thursday, January 17, 2008

Delphi Tips and Tricks: Selecting Tool Palette Items

There is a really easy way of selecting items in the Tool Palette from the keyboard: CTRL + ALT + P then just type the component you want.

Thursday, January 3, 2008

Delphi Tips and Tricks: Single Line Comments

A useful feature of the latest versions of Delphi and C++Builder is CTRL + /. This will place a single line comment, //, in front of every line that is selected or that the cursor is on. It will also remove the comment. Very quick and easy.

Monday, June 4, 2007

Delphi Tips And Tricks: CoInitialize/CoUninitialize Part I

Have you ever been thinking about something and started noticing it all over the place? I find this happens when looking to buy a car. This phenomenon started happening for me lately with CoInitialize. CoInitialize has come up a dozen or more times in the last few months and then again last week, so I decided to start a little series on CoInitialize and CoUninitialize. Since this is a common source of problems for COM applications, even people who know better, I think everyone will benefit from reading this.

In this post I want to go over a bit more than just CoInitialize and CoUniniitalize, I want to show you how Delphi compiler magic can cause you problems when initializing the COM Library. Take the following program, that does just about nothing but cause an error:


program Project1;

{$APPTYPE CONSOLE}

uses SysUtils, ActiveX, XMLintf, XMLDoc;

var
Document: IXMLDocument;
begin
CoInitialize(nil);
Document := TXMLDocument.Create('foo.xml');
CoUninitialize;
end.


This very simple program, calls CoInitialize, creates a TXMLDocument and then calls CoUninitialize. The failure happens after the CoUninitialize. Do you know why?

Delphi manages the lifetime of interfaces calling IUnknown._AddRef on an interface assignment and IUnknown._Release on cleanup of the method. In this case, the COM Library has already been cleaned up when the destructor of TXMLDocument occurs. So really this very simple program, calls CoInitialize, creates a TXMLDocument, increments the reference count of IXMLDocument, calls CoUninitialize, decrements the reference count and destroys the object. We need to change the program so the call to IUnknown_Release happens before CoUninitialize. The simplest way to solve this problem is to change the program by adding a method:


program Project2;

{$APPTYPE CONSOLE}

uses SysUtils, ActiveX, XMLintf, XMLDoc;

procedure DoSomething;
var
Document: IXMLDocument;
begin
Document := TXMLDocument.Create('foo.xml');
end;

begin
CoInitialize(nil);
DoSomething;
CoUninitialize;
end.


Now this very simple program, calls CoInitialize, creates a TXMLDocument, increments the reference count of IXMLDocument, decrements the reference count and destroys the object, calls CoUninitialize.

Thursday, May 24, 2007

Delphi Tips and Tricks

One of the most horrible features of Delphi is the fact that every class in the same unit have access to one another privates. This is similar to a friend class in C++ which should be used sparingly. As usual Delphi makes things easy which I guess is a good thing but like I said this is a horrible feature of the language. It ranks up there with "with". But like any horrible feature there are times when you can use it to your advantage. If a class is in a different unit but you need to get to the protected section just declare local class that derives from the class in question and cast your class to the local derivative and BAM! For example, take a look at CustDlg.pas:


type
THack = class(TWinControl);
THack2 = class(TControl);

procedure TCommandDockObject.EndDrag(Target: TObject; X, Y: Integer);
var
R: TRect;
begin
if Target is TToolBar then
begin
R := Control.BoundsRect;
R.Right := R.Left + TToolBar(Target).ButtonWidth;
THack2(Control).UpdateBoundsRect(R);
Control.Visible := True;
if not TToolBar(Target).AutoSize then
begin
TToolBar(Target).AutoSize := True;
TToolBar(Target).AutoSize := False;
end
else THack(Control.Parent).AdjustSize;
end;
inherited EndDrag(Target, X, Y);
end;


This feature of the language is being used to get access to TWinControl.AdjustSize and TControl.UpdateBoundsRect. Sick, isn't it?