This article describes how the application adds an icon to the taskbar notification area through a small program SSLAUNCH, how to disable multiple Win32 instances, and the relevant content of the screen saver.
SSLAUNCH is written in C language, compiled with Visual C 5.0, is a program based on the modeless dialog, which is forbidden to have multiple instances, ie one instance can be run once. The taskbar notification area icon is added when the dialog is initialized, the dialog response to the callback message defined, when the left mouse button is pressed, pops up the context menu filled by the screen saver name. Delete the taskbar notification area icon when the dialog is turned off (ie program exit). If the reader is interested, it can easily transplant it into an MFC-based program.
1, taskbar notification area
There is a notification area in the taskbar of Windows 95, and an application can put an icon into it to represent an operational state, and can have a tool associated with it as a description control. When the mouse appears within the rectangular boundary of this icon, send the application defined callback message to the corresponding application. The application adds, modifies, and deletes the taskbar icon by sending messages. The message is sent by calling the function shell_notifyicon. If the call is successful, returns true; otherwise, return false. The shell_notifyicon function is as follows:
Winshellapi Bool WinApi Shell_notifyicon
DWORD DWMESSAGE, // Message Identifier
PNOTIFYICONDATA PNID // Notifyicondata Structure
);
The message identifier can be:
NIM_ADD adds icon to the taskbar notification area
NIM_DELETE deletes icons from the taskbar notification area
NIM_MODIFY Change Task Bar Notification Area Icon
Notifyicondata structure:
Typedef struct _notifyicondata {
DWORD CBSIZE;
Hwnd hwnd;
UINT UID;
UINT UFLAGS;
Uint ucallbackmessage;
Hicon Hicon;
Char sztip [64];
Notifyicondata, * PNOTIFYICIONDATA;
among them:
CBSIZE Notifyicondata Structure Size
HWND receives a callback message window handle
UID taskbar notification area icon identity
UFLAGS specifies those members in this structure valid
UCALLBACKMESSAGE application definition callback message
HICON Task Bar Notification Area Icon Handle
Sztip taskbar notification area prompt string
The parameter uflags can be a combination of the following values:
NIF_ICON taskbar notification area icon is valid
Nif_Message application defined callback message is valid
Nif_tip taskbar notification area prompt string is valid
a. Add to the taskbar notification area icon
Bool Sslaunch_oninitdialog (HWnd Hwnd, HWND HWNDFOCUS, LPARAM LPARAM)
{
// add an notification icon to the taskbar
NotifyCondata Nid;
Notifyicondata NID;
Nid.cbsize = sizeof (nid);
Nid.hwnd = hwnd;
Nid.uid = idi_sslaunch;
Nid.uflags = nif_message | NIF_ICON | NIF_TIP;
Nid.ucallbackMessage = WM_SSLAUNCHICONNNOTIFY;
Nid.hicon = loadicon (GetWindowInstance (HWND),
KeintResource (IDi_sslaunch);
LSTRCPYN (Nid.sztip, g_szappname, sizeof (nid.sztip) /sizeof(Nid.sztip[0]) etc return (SHELL_NOTIFYICON (NIM_ADD, & NID))
}
b. Delete of the taskbar notification area icon
When the application exits, you should delete the corresponding icon on the task notification area:
Void sslaunch_ondestroy (hwnd hwnd)
{
// Remove the notification icon from the taskbar
Notifyicondata NID;
Nid.cbsize = sizeof (nid);
Nid.hwnd = hwnd;
Nid.uid = idi_sslaunch;
Shell_Notifyicon (Nim_Delete, & Nid);
}
c. Application defines the reception of the callback message
If the callback message is specified for the taskbar notification area, the system will occur when the mouse event occurs in this area.
Send this message to the application, where wparam is a taskbar notification area icon identifier, lParam
It is the mouse information after the mouse event.
Void Sslaunch_oniconnotify (WParam WPARAM, LPARAM LPARAM)
{
UINT UID = (UINT) WPARAM;
UINT UMSG = (UINT) LPARAM;
IF (uid == idi_sslaunch) {
Switch (UMSG) {
Case WM_LBUTTONDOWN:
// do somthing
Break;
Case WM_LBUTTONUP:
// do somthing
Break;
DEFAULT:
Break;
}
}
}
2. Prohibit multiple Win32 instances
We will discuss the WinMain function before discussing multiple Win32 instances. We know that any GDI-based Windows program is called by the WinMain function as an entry. In Win16, HPREVINSTANCE points to the handle of the forward instance, but in Win32, each process has a separate 4G address space, from 0 to 2G, it is a process, which is invisible to other processes. Therefore, in Win32, HPREVINSTANCE is always NULL.
Int Winapi WinMain
Hinstance Hinstance, // Handle to Current Instance
Hinstance Hprevinstance, // Handle to Previous Instance
LPSTR LPCMDLINE, / / POINTER TO COMMAND LINE
Int ncmdshow // show State of window
);
Thus, in Win32, it is not possible to determine if another instance of the HPREVINSTANCE is NULL to determine if another instance of one program exists, and use other methods to determine.
method one
Use the FindWindow function to find the specified window. If successful, return the handle of the window you are looking for, otherwise return null, thereby determining another instance of a program exists.
The code snippet of the following picture shows how to use the FindWindow function:
Tchar szclassname [] = _text ("My Wnd Class");
Tchar szWndname [] = _text ("my wnd");
HWND HWND = FindWindow (SzclassName, SzWndName);
IF (hwnd) {
Messagebox (NULL, _Text ("Another Instance Is Already Running."), _Text ("Information"), MB_OK | MB_ICONITIONFORMATION
}
It should be noted that the various instances of the probability program have different window names, if the following calls FindWindow
HWND HWND = FindWindow (SzclassName, NULL);
Find all the windows and match the window class name, if you can guarantee your window class name, then you can trust FindWindow, otherwise you need a better way.
Method Two
Data is shared by sharing data between the EXE to determine if there is another instance of the program.
Each EXE or DLL is consisting of a collection of segments, in the Win32 program, each segment begins at point (.). For example, when the compiler is a compiler, put all the code in a segment called .Text, put all uninitialized data into the .bss segment, put all initialized data into the .data segment.
You can give one or more attributes for each segment (hereinafter, some segment properties that are common):
Data readable in the READ segment
The data in the WRITE segment can be written
The data in the Shared section can be shared by multiple instances
The data in the Execute section can be executed
You can generate segments with the following instructions:
#pragma data_seg ("Shared")
Static long g_linstancecount = -1;
#pragma data_seg ()
When the compiler generates this code, generate a new segment, and put the initialization data after the #pragma data_seg ("Shared" instruction, in the new section Shared, the unintered data is put into the .bss segment. #pragma data_seg () After the data is placed back to the default data segment.
Only tell the compiler to put specific data into your own segment is not enough to share them, but also tell the linker to share in a particular segment. The properties of this segment can be specified when linking.
/ Section: Shared, RWS
Segment name attribute
When the program is initialized, for example, when calling the WinMain function, call the interlockedInCrement function to add the variable in the shared segment plus 1, you can determine that a program has several instances running by judging the value of the variable within the shared section. The following code demonstrates how to determine a running program instance is the first instance of this program.
Bool BisfirstInstance = (InterlockedIncrement) == 0);
IF (! bisfirstinstance) {
MessageBox (NULL, _Text ("Screen Saver Launcher Is Already Running."), G_szappname,
MB_OK | MB_ICONITIONFORMATION
}
Make the shared section to add 1, not using G_LinstanceCount , but use InterlocKedInCrement (& g_linstancecount), because the InterlocKedInCrement function synchronizes the variable's access (Synchronize), block multiple threads simultaneously access the same variable. See the documentation about Win32 SDK for thread synchronization.
There are many ways to prohibit multiple Win32 instances, such as Win32 core objects (Mutex, Semaphore), global atoms, etc. can be used to ban multiple Win32 instances, where we only introduce the above two methods.
3. Screen Saver Launch: The screen saver is a standard Windows executable program that SCR is an extension. When editing a list of available screen saver, the Control Panel Desktop applet looks for the extension of the SCR's Windows-based executable, if the Windows directory and system directory are the same files at the same time. The name of the screen saver ignores the one in the Windows directory. Any deliberate troubleshooting (such as a text file or DOS is changed to SCR) WINDOW95 is ignored, but the Windows 95 and NT will not change the extension of the standard Windows executable to SCR. aware. This is only extremely extreme, I believe that users will not adopt this practice to "test" your Windows.
Standard WIN32-based screen saver must be written in strict standards, please refer to the Win32 SDK documentation for details. What you need herein is that all WIN32-based screen saver requires a description string that does not exceed 25 characters. In the resource string table of the screen saver, the identity of the string must be 1.
But we found that the screen saver under Windows 95 is not entirely strictly written according to the standard. When editing a list of available screen saver, the Control Panel Desktop applet simply adds the file name of the screen saver to the list, not join. The description string mentioned above. Under Windows NT, the system strictly distinguishes the standard and non-standard screen saver. For standard screen saver, the system gets its description string and displays it in the list of screen saver; for non-standard screen saver, the system only adds its file name to the list.
Since Windows 95 and Windows NT's list of screen savers are slightly different, this is described herein. For the difference, SSLAUNCH under Windows 95 indicates SSLAUNCH95, and SSLAUNCH under Windows NT is represented by SSLaunchnt.
SSLAUNCH95 uses the WINDOW 95 to call the screen saver, search the screen saver in the startup directory of Windows 95, add the file name to the taskbar Notification area icon context menu, click the mouse to start the appropriate screen saver. Windows 95 saves the screen saver name selected in the user in the System.ini file /boot/scrnsave.exe. SSLAUNCH95 compares the user-selected screen saver name and searched screen saver name, if the same is the same, the corresponding menu item setting check mark is set in the taskbar notification area icon context menu, to indicate whether this screen saver is current user Chosen. SSLAUNCH95 does not determine if the screen saver under the Windows launch directory is a true screen saver, because Win32 under Windows 95 cannot easily determine whether an SCR file is a GDI-based Windows executable (NE or PE format). The author found two functions that can be used to determine the file type: SHGETFILEINFO, GetBinaryType. SHGETFILEINFO can determine. EXE, .com, .bat several file types, but think .scr file is not executable; getBinaryType can easily determine the file type, but Windows 95 does not support, just simply return ERROR_NOT_IMPLEMENT, while Win32 But support it.
Click to schematically
SSLAUNCH95 can also run in Windows NT, but the pop-up context menu cannot be filled with the screen saver, and cannot determine if the SCR is a GDI-based Windows executable. Here, SSLAUNCHNT describes the discrimination of the SCR file under Windows NT, and the method of describing the screen saver from the SCR file resource.
a. Discipline for the SCR file
Windows NT provides support for the getBinaryType function, so this function can be used to determine if an SCR file is a Windows executable program, and it is determined that it is a WIN16 or Win32 executable. This is important because, for Win32-based SCR files, we have important information in its string resources later, and description strings for the screen saver. It should also be noted that lpapplicationName should give a full path, otherwise it looks for files only in the path where the process is located, which will cause errors, so that the information of the .scr file in the Windows launch directory cannot be returned.
Bool getBinaryType
LPCTSTR LPAPPLICATIONNAME,
LPDWORD LPBINARYTYPE
);
After the getBinaryType is successful, the DWORD points to LPBINARYTYPE returns to the following values:
SCS_32bit_binary based application
SCS_DOS_BINARY Application Based on MS-DOS
SCS_OS216_BINARY Application Based on 16-bit OS / 2
PIF file for SCS_PIF_BINARY MS-DOS Application
SCS_POSIX_BINARY Based on POSIX-based applications
SCS_WOW_BINARY Based on 16-bit Windows application
b. String of the screen saver file from the SCR file string resource
When we judge a Win32-based SCR file, we can start to get its string. In WIN32, there is a simple and effective way: putting an EXE or DLL file in a data file mode, call the loadLibraryEx function.
Hinstance LoadLibraryEx (
LPCTSTSTSTLIBFILENAME, / / EXE or DLL file name
Handle Hfile, // Reserved parameters, must be NULL
DWORD DWFLAGS / / Function Inlet Sign
);
DWFLAGS can be a combination of 0 or below:
Dont_resolve_dll_references The system maps the DLL to the address space of the process without calling the DLLMAIN function.
The load_library_as_datafile system maps the DLL to the address space of the process as a data file, and does not call the DLLMAIN function. If you want to get the resource in EXE, you can also call the loadLibraryEx function to map the exe to the process address space.
LOAD_WITH_ALTERED_SEARCH_PATH will change the method used by LoadLibraryEx when positioning the DLL file.
When you call LoadLibraryEx in the way to load_library_AS_Datafile, the system simply creates a file image object, map the DLL (exe) to the address space of the process, and does not call Dllmain (Winmain). If the call is successful, the function returns a HINSTANCE, which is mapped to the DLL (EXE) load address of the process space, so that the loadString function can be called, and the designation is obtained from the string resource table of the DLL (EXE) file. String.
Click to schematically