|
|
-
Recently I need to add full screen mode for one of my MFC projects. Like what we did usually, my first impression is to hide the tool bar of main frame and expand the size of view. Thus, I need to calculate the system screen size (GetSystemMetrics() API), to calculate the current size of windows frame (GetWindowRect() API), and to reset the location/coordinator of main frame( SetWindowPos() API).
It is not hard, but it really took me much time on implementating it. Then, I tested it and found the full screen mode can be displayed. However, when I tried to go back to normal size, my Ribbonbar dissappeared! Thus, I realized that I need to do more work about Ribbon bar. When I read the documentation on MSDN, fortunately I found a very interesting class "CFullScreenImpl" class in MFC. http://msdn.microsoft.com/en-us/library/cc308980.aspx
Thus, I tried it in my Visual Studio 2010. Easy!!! You only need to do three things:
- Create a button or check box or any control (you want users to click) to get full screen mode. Remmember its ID, for example, ID_VIEW_FULLSCREEN
- In MainFrm.cpp, at the end of OnCreate() API, write two lines
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
............
// enable full screen mode
EnableFullScreenMode (ID_VIEW_FULLSCREEN); // the ID of your control you created in step 1
EnableFullScreenMainMenu(FALSE);
return 0;
}
3. In MainFrm.cpp, add an event handler function for your control in step (1), and add ShowFullScreeen().
void CMainFrame::OnViewFullscreen()
{
ShowFullScreen();
}
That is it! Very simple! I hope more and more people can enjoy it!
|
-
My machine has 32-bit Vista and Visual Studio 2008, so I followed the following article to create a COM server using Wizards.
http://msdn.microsoft.com/en-us/library/dssw0ch4.aspx
Unfortunately, I couldn't compile the test client application. Eventually I found a work around..
- The 4th line should be #import "..\MyServer\Debug\MyServer.tlb" no_namespace
- The 13rd line should be spUnknown.CoCreateInstance(__uuidof(Object1));
If you are a beginner like me, maybe this will be helpful.
|
-
Well, when you write your first win32 console application in Visual Studio 2008, you probably just want to click F5 and test if it runs or not. Unfortunately, probably you will get some trouble as I did. I collected three "confusing" errors here.
- Error spawning 'rc.exe'
- Error 1 fatal error LNK1181: cannot open input file 'kernel32.lib'
- Work-around: use Windows SDK Configuration Tool to change the headers/libs that Visual Studio 2008 refers to v6.0A.
- Error result 1 returned from 'c:\program files\Microsoft SDKs\windows\v6.0A\bin\rc.exe'
- Work-around: turn off "Incremental Linking"
I am not sure if there are other scenarios which caused these errors. Just for my experience, because my computer was installed with Windows SDK partially.
|
-
Well, this title looks complicated...actually the story is pretty simple by using an example.
For example, you write an application APP_A and the installer of this application needs to leave fingerprint on system's registry keys, so that the other applications/users can know APP_A is installed on the system. Assuming that "fingerprint" is "HKLM\Software\Microsoft\App_A", and you selected the target platform as "Any CPU" when you build it, it looks like that you are done. However, if your APP_A is installed on 64-bit OS, the other 32-bit application will complain that it can not detect APP_A.
Why? Simply because registry REDIRECTION. Because here HKEY_LOCAL_MACHINE\Software is redirected to HKEY_LOCAL_MACHINE\Software\Wow6432Node.[However, please note that HKEY_CURRENT_USER has no redirection here].
Therefore, if your application wants to support the access of those 32-bit applications/processes on 64-bit OS, you need to leave fingerprints on both WoW6432Node and regular node of HKLM registry key. About registry redirection, more information is at http://msdn.microsoft.com/en-us/library/aa384232(VS.85).aspx
[PS: how do you know the application is 32-bit or 64-bit? Use "dumpbin", a command line tool. for example, on 64-bit OS, %windir%\syswow64\cmd.exe is a 32-bit command shell and %windir%\system32\cmd.exe is the 64-bit command shell (the default one on the start menu)]
|
-
Recently I need to write some codes to disable one feature on Windows 7 for an application. For Windows 7, its major number is 6 and minor number is 1 (see this link http://msdn.microsoft.com/en-us/library/ms724832(VS.85).aspx) and thus we can compare the version number to detect that. However, that is not enough. Because Windows Server 2008 R2 also use this version number, we have to filter it further by using product type. In our managed code, System.OperatingSystem can retrieve version number easily, but there is no available API for retrieving product type, so we have to wrap native function GetVersionEx(). Something like this:
if (osInfo.Platform == System.PlatformID.Win32NT && osInfo.Version.Major == 6 && osInfo.Version.Minor == 1)
{
if (SafeNativeMethods.GetVersionEx(versionInfo))
{
if (versionInfo.wProductType == ProductType.Windows_Workstation)
{
// This is Windows 7
}
}
}
[DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal extern static bool GetVersionEx([In, Out] OSVERSIONINFO pVersionInfo);
However, it is NOT GOOD! Sorry for that.......Let us read this MSDN web page:
http://msdn.microsoft.com/en-us/library/ms724832.aspx
It points out at least two points:
- If you must require a particular operating system, be sure to use it as a minimum supported version, rather than design the test for the one operating system. This way, your detection code will continue to work on future versions of Windows.
- Rather than using GetVersionEx to determine the operating system platform or version number, test for the presence of the feature itself.
Obviously, GetVersionEx() is not suitable here. VerifyVersionInfo() should be the friend. The following link gives very good example in C++ to show how to detect if the OS is Windows XP SP2 or later.
http://msdn.microsoft.com/en-us/library/ms725491(VS.85).aspx
Following the example in above link, we can wrap VerifyVersionInfo() in managed code to detect if the running OS is Windows 7 or later.
|
-
Recently I am working with Windows Installer and think ProductCode, UpgradeCode and PackageCode are very basic but very important concepts, so I make a conclusion here for references. Both ProductCode and UpgradeCode can be viewed from Property table in MSI package, and PackageCode can be reviewed from View->Summary information if you view MSI through Orca (which is shipped with Windows SDK.)
What is UpgradeCode in the MSI package?
The upgrade code is the unique GUID of identifying a family of a product. That is, the same products with different versions have probably been shipped for a few releases. These products have different ProductCodes, but they are linked together by using SAME UpgradeCode. For example, assuming that we wrote a product called "Happy MSI" and this product only has one MSI package for deployment on client system. The first release of this product is actually the MSI package with name "version_1.msi", and the second release is "version_2.msi". Then, these two MSI must have same UpgradeCode. When users run "version_2.msi" on their system, the windows installer will use the UpgradeCode to decide if previous versions of this product are already present on the system. Installer API "MsiEnumRelatedProducts()" uses the UpgradeCode to query all the family products.
What is ProductCode in MSI Package?
The product code is the unique GUID of identifying an application or product release; In other words, different versions and languages of Product must have different product codes. http://msdn.microsoft.com/en-us/library/aa370854(VS.85).aspx. Also, ProductCode can be used to query feature state, and product state. For example, installer API "MsiQueryFeatureStateEx()" and "MsiQueryProductState()", etc.
What is PackageCode in MSI Package?
Similar, the package code is the unique GUID identifying a particular Windows Installer package. Here, package mapps to a physical file with extension name ".MSI". Remember, a product consists of one or multiple (MSI) packages, and one package also can be shared among different products. The combination of ProductCode and PackageCode is used to determine if the users want to reinstall the product or not. I found the book "The Definitive Guide to Windows Installer" has the best explaination on this. There are four scenarios:
- If you install same product (same ProductCode) from the same package (same PackageCode), it means you want to go to "repair" or "uninstall" mode.
- If you install same product (same ProductCode) from the different package (different PackageCode), it is not allowed. You willl get message "Another version of this product is already installed", and you have to remove the existing installed product before you install the new one.
- If you install different product (different ProductCode) from the package (same PackageCode), it would go into maintenance mode and ask for a repair or remove.
- If you install different product (different ProductCode) from the package (different PackageCode), the installer will think it is a NEW product and let you go ahead.
|
-
Common scenario is that a developer wrote an application on his/her dev machine A (which has source code, etc), and wants to debug this application's source code when the application is running on the remote machine B. Visual Studio 2008 provides two ways to help with this scenarios easily. Read the http://msdn.microsoft.com/en-us/library/bt727f1t.aspx. Basically, you can use "Attach Process" way to attach the program which runs on the remote machine to debug it, and you also can "Start the external program" that you want to debug on the remote computer. Usually I use the second way, because it is very easy for debugging the launching process.
Here, I summarize a few steps to run the Remote Debugging Monitor (msvsmon.exe) on the remote computer B and set properties of Visual Studio for remote debugging a managed (C#) application.
The details steps are
- Share msvsmon.exe on a file server, for example \\MyMachine\x64\msvsmon.exe
- On the remote machine B double click msvsmon.exe from the above file share link
- After the remote debugging monitor launched, go to the Tools->Options, make sure your dev machine A has permission over there
- On your dev machine A, open the corresponding project in VS 2008, go to project properties->Debug, set the following paramters
- Start Action->Start external program: \\remotemachine\applicationExample.exe
- Start Options->Command line arguments: -your ags (if your application needs)
- Start Options->Use remote machine (checked the check-box) : YourRemoteMachineName (make sure it is matched with the one you can see on Debugging Monitor dialog box Tools->Options->RemoteName) [See the following picture]
- Click F5
That is it! You can debug it as if the application is running on your dev machine (the application is actually running on the remote machine). :)
Key point: Make sure your application is built with symbols.
|
-
A couple of weeks ago I tried to implement a glass window in C# application. My first thought is to edit the properties of WinForm. For example, I modified the "BackColor" and "Opacity" of the Form and did see the form became transparent and its color was close to the windows frame. However, it didn't match with the windows frame smoothly and it was not a real glass window! Thus, I read some articles from website and realized the trick of "glass" window is to "Extend the Windows Frame" to the client area on the windows form. Of course it makes a lot of sense. As Vista's windows frame is a glass style, the window certainly will become glass window if we extend its frame to the client area. Further, I had to import the Vista API to my C# by
[DllImport("dwmapi.dll")]
internal static extern void DwmExtendFrameIntoClientArea(System.IntPtr hWnd, ref Margins pMargins);
This API looks simple, but it includes some concepts.
- What is Margin?
- What is Client Area?
- Is that enough to create a glass window by this API?
It is easy to find their definitions and information from MSDN. I would like to use some pictures to illustrate the idea.
  
We name the above three pictures from left to right as Figure 1, Figure 2 and Figure 3. The title of every picture (Windows Form) implies what I am trying to illustrate. Figure 1 is the snapshot of a Windows Form that I created by Visual Studio C# Windows Form Application template (only modified its size and addeda button). The client area is the editable area for clients. It excludes the title bar, icon, windows border, etc). Figure 3 is the snapshot of a Glass Window I created. Then, in order to achieve the effect of Figure 3, what I should do?
-
Define your margin. The margin structure is defined by its TOP, LEFT, RIGHT, BOTTOM size (the distance from the client area border). For example, Figure 2 displays my defined Margin area by Black color, where its TOP=50, BOTTOM=50, LEFT=30, RIGHT=30
-
Call DwmExtendFrameIntoClientArea() API to extend the windows frame to the margin area (passing your above Margin as one of input parameters). Now, the margin area became the extended frames! The black area is extended frame and the white area (much smaller compared with Figure 1) became new client area in Figure 2.
-
Paint your Margin (Extended Frame) area as BLACK. How to paint? Divide the margin area into 4 rectangles, refer to Figure 2.
rect_1 = new Rectangle(0, 0, this.ClientSize.Width, m.Top);
rect_2 = new Rectangle(0, m.Top, m.Left, this.ClientSize.Height- m.Top-m.Bottom);
rect_3 = new Rectangle(this.ClientSize.Width - m.Right, m.Top, m.Right, this.ClientSize.Height - m.Top - m.Bottom);
rect_4 = new Rectangle(0, this.ClientSize.Height - m.Bottom, this.ClientSize.Width, m.Bottom);
It is done. Here are the links I think very useful and resourceful.
|
-
Besides using Code Analysis (was FxCop), Source Analysis (was StyleCop) and Unit Test Code Coverage tool in Visual Studio IDE, I like some tools shipped in Windows SDK. These tools are very cool.
Of course, besides the above tools there are a lof of other great tools. Also, you can try the Samples shipped in Windows SDK. Some of them are very cool too. :)
|
-
As we know, both Visual Studio IDE and its Command Prompt provide build environments to build our C++ applications, but they have some differences. I concluded some features of them as following.
(1)In the VS Command Prompt, if you use "/useenv" switch to launch your VS IDE, then the VS IDE will use the environment variables (PATH, LIB, LIBPATH, INCLUDE, etc) to set the compiler settings (load these environment variables into the VC++Directories), which leads that VS IDE has the same build settings as VS Command Prompt for compiling C++ applications.
(2) VS Command Prompt actually uses a batch script (Common7\Tools\vsvars32.bat) to set the build environment. It is very simple and straightforward. How can you figure it out? Easy. You can right click VS Command Prompt and see its Properties, and then you know it is linked to a batch file. You can trace the batch file to find out the target batch script.
(3) VS IDE (VCBuild) does not really use the batch script file (again, unless you use /useenv). I am not very sure of its internal mechanism. As far as my understanding, its opions (Tools->Options->Projects and Solutions->VC++ directories) are either from .config configuration files or from VCComponents.dat. That is, if users make any changes on the VC++ Directories setting, VCComponents.dat (AppData\Local\Microsoft\VisualStudio\9.0\VCComponents.dat, e.g. it is Vista and VS 2008) will be generated or updated. This file is per-user and per-machine.Whenever users launch Visual Studio, Visual Studio will read the settings from VCComponents.dat. If VCComponents.dat does not exist, then VS will read the setting information from VCProjectEnginee.dll.config (Program Files\Microsoft Visual Studio 9.0\VC\vcpackages, for each platform) configuration file.
(4) VS IDE provides both local setting and global setting. For example, Tools->Options->Projects and Solutions->VC++ Directories->Include, which is a global setting for headers which are used in all projects; Properties->Configuration Properties->C/C++->General->Additional Include Directories, which is a local setting for headers which only affects one project.
|
-
Sometimes you will see a managed assembly have both strong name and authenticode signature and are confused about their differences. Simply speaking, they use different mechanisms to help users to judge if the assembly comes from a trustable source. Also, strong-name sign is only for .NET managed assembly, and Authenticode sign is for both managed and native assembly.
Strong-name Sign
There is a good article about strong name signature http://msdn.microsoft.com/en-us/magazine/cc163583.aspx. Simply there are a few points worthy note:
- If an assembly is installed to GAC, this assembly has to be strong-name signed.
- If the target application is strong-name signed, all the references must be strong-name signed too.
Note: if your assembly is delay signed with strong name, you have to install "Strong Name HiJack" Tool in order to run it. Also, if you want to verify if it is strong name signed. Easy, you can use "sn.exe" (A command line too shipped with Windows SDK) by typing "sn.exe -vf myAssembly.exe"
Authenticode Sign
Authenticode uses chaining certificates in digital signatures to identify the "authentic author" of the assembly. Its mechanisms is that some publishers registerred their information in an organization which is Certification Authority (CA). The CA assigns a unique certificate to the assembly. However, CA can reovke the certificate if needed and this certificate is only valid for a period of time. Thus, authenticode sign has following features
- The authenticode signed assembly is not always valid.
- The authenticode signed assembly probably has a perfomance issue, because it needs to connect with network to download the up-to-date (List of Revoked Certificates) CRL to ensure the certificate is valid.
|
-
A few command SQL script
(1) Insert multiple records of Table_A to a new Table_B
SELECT *
INTO Table_B
FROM Table_A
(2) Insert multiple records of Table_A to an existing table Table_B
INSERT INTO Table_B (Col1, Col2, Col3)
SELECT ColM, ColN, ColQ FROM Table_A
(3) Update Table_A through the data of Table_B
UPDATE Table_A
SET Col1=Table_B.Col2
FROM Table_B
Note: the above scripts can be easily extended to multiple tables, because multiple tables can be joined to one table. For example, if we want to update Table_A by the joined information of Table_B and Table_C, we can do the following
Update Table_A
Set Col1=myTable.ColM, Col2=myTable.ColP
FROM
(
SELECT Table_B.ColM, Table_C.ColP
FROM Table_B
INNER JOIN Table_C
ON Table_B.ID=Table_C.RefID
) AS myTable
|
-
A few months ago I read two articles on MSDN about the compatibility
One is http://msdn2.microsoft.com/en-us/library/58bc9k67(VS.71).aspx The other is http://msdn2.microsoft.com/en-us/library/58bc9k67(VS.80).aspx
The first link said, “Backward compatibility means that an application is compiled for an earlier version of the .NET Framework, and continues to execute on later versions of the .NET Framework, without any degradation of functionality”.
The second link said “Backward compatibility means that an application is compiled for a newer version of the .NET Framework, but continues to run on earlier versions of the .NET Framework without any loss of functionality.”
My first impression was that the above two definitions are opposite. One of them must be wrong. Later, after carefully considering I realized these two articles look similar, but they were telling different stories. The first article was saying the backward compatibility of the .NET Framework, while the second article was saying the backward compatibility of a given application. In other words, the first link was referring to,: "Backward compatibility of Framework means ...." and the second link was referring to, "Backward compatibility of Application means ....".
The name of backward compatibility actually self-explains the definition, but in case you were confused by something else, here is a good link http://en.wikipedia.org/wiki/Backward_compatibility
|
-
It is not unusual to see a lot of switch statements or multiple if else statements in OO codes. From the view of code maintainability, probably some of such codes need refactoring. Strategy pattern is a good replacement.
For example, the old code is like:
internal void Run()
{
int[] numbers = { 2, 1, 5, 6 };
Sort(numbers, SortType.QuickSort);
}
void Sort(int[] numbers, SortType type)
{
switch (type)
{
case SortType.QuickSort:
QuickSort(numbers);
break;
case SortType.MergeSort:
MergeSort(numbers);
break;
....
}
....
}
Thus, it is a good chance to apply strategy pattern here. The new code is like:
internal void Run()
{
int[] numbers = { 2, 1, 5, 6 };
Context context= new Context (new QuickSort(numbers));
context.Sort();
}
There are a lot of resources about strategy pattern, so here I will skip other parts to complete the above code. As you can see, in the future, if we have new Sort algorithm, we do not need to modify the implementation big Sort(int[] numbers, SortType type) method (described in the old code). Instead, we just need to add a new class to implement the ISortAlgorithm interface. It reflects the open-close principle and improves maintainability of codes.
|
-
Recently I uninstalled my VS 2008 and tried to install VSTS 2008. Unfortunately I was blocked by a couple of setup errors. Thus, I found a couple of good links/tools.
Generally speaking, if we want to uninstall VS 2008 and reinstall a new VS 2008, we can use the tool of Windows Install Cleanup to remove the components described in the link http://go.microsoft.com/fwlink/?LinkId=85096. That cleanup tool is very fast.
|
|
|
|