Start Screen saver from task notification area

Source: Internet
Author: User
This article describes how an application adds icons to the taskbar notification area, how to disable multiple Win32 instances, and how to enable the screen saver through sslaunch, a small program that quickly starts the screen saver.

Sslaunch is written in C language and compiled in Visual C ++ 5.0. It is a program based on a mode-free dialog box. Multiple instances are prohibited at the same time, that is, only one instance can be run at a time. The taskbar notification area icon is added when the dialog box is initialized. The callback message defined by the Response Program in the dialog box is displayed. When you press the left mouse button, a context menu filled by the screen saver name is displayed. When the dialog box is closed (that is, the program exits), the taskbar notification area icon is deleted. If you are interested, you can easily transplant it into an MFC-based program.

1. taskbar notification area

There is a notification area in the taskbar of Windows 95. The application can put an icon in it to indicate the operation status, and a tool associated with it can be used as a description control. When the mouse appears within the rectangle 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 shell_policyicon function is called to send messages. If the call is successful, true is returned. Otherwise, false is returned. The shell_policyicon function has the following prototype:
Winshellapi bool winapi shell_policyicon (
DWORD dwmessage, // message identifier
Pnotifyicondata pnid // notifyicondata Structure
);
The message identifier can be:
Nim_add add an icon to the taskbar notification area
Nim_delete Delete icon from the taskbar notification area
Nim_modify: Change the taskbar notification area icon
Notifyicondata structure:
Typedef struct _ policyicondata {
DWORD cbsize;
Hwnd;
Uint uid;
Uint uflags;
Uint ucallbackmessage;
Hicon;
Char sztip [64];
} Notifyicondata, * ppolicyicondata;
Where:
Cbsize yyicondata structure size
Hwnd receives callback message window handle
ID of the UID taskbar notification area icon
Uflags indicates that the Members in the structure are valid.
The callback message defined by the ucallbackmessage Application
Hicon taskbar notification area icon handle
Sztip taskbar notification area prompt string
The uflags parameter can be a combination of the following values:
The nif_icon is valid in the notification area of the taskbar.
The callback message defined by the nif_message application is valid.
The prompt string of the nif_tip taskbar notification area is valid.
A. Add the taskbar notification area icon
Bool sslaunch_oninitdialog (hwnd, hwnd hwndfocus, 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_sslaunchiconnotify;

Nid. hicon = loadicon (getw.winstance (hwnd ),

Keintresource (idi_sslaunch ));

Lstrcpyn (NID. sztip, g_szappname, sizeof (NID. sztip)/sizeof (NID. sztip [0]);

  

Return (shell_policyicon (nim_add, & nid ))

}

B. Delete the taskbar notification area icon

When the application exits, the corresponding icon in the notification area of the task should be deleted:
Void sslaunch_ondestroy (hwnd)

{

// Remove the notification icon from the taskbar

  

Notifyicondata NID;

Nid. cbsize = sizeof (NID );

Nid. hwnd = hwnd;

Nid. uid = idi_sslaunch;

  

Shell_policyicon (nim_delete, & nid );

}

C. The application defines the receipt of callback messages

If a callback message is specified for the taskbar notification area, the system displays the callback message when a mouse event occurs in this area.

Send this message to the application, where wparam is the identifier of the taskbar notification area icon, lparam

Is the mouse information after a mouse event occurs.

  

Void sslaunch_oniconnotify (wparam, 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

Before we discuss how to disable multiple Win32 instances, we should first discuss the winmain function. We know that any windows program based on GDI uses the winmain function as the portal and is called by the system. In Win16, hprevinstance refers to the handle of the previous instance. However, in Win32, each process has an independent 4G address space, from 0 to 2g, which is private to the process, it is invisible to other processes. Therefore, in Win32, hprevinstance is always null.

  

Int winapi winmain (

Hinstance, // handle to current instance

Hinstance hprevinstance, // handle to previous instance

Lpstr lpcmdline, // pointer to command line

Int ncmdshow // show state of window

);

  

Therefore, in Win32, it is not possible to judge whether hprevinstance is null to determine whether another instance of a program exists. It should be determined by other methods.

  

Method 1

Use the findwindow function to find the specified window. If the window is successful, the handle of the window to be queried is returned. Otherwise, null is returned, so that you can determine whether another instance of the program exists.

  

The code snippet demonstrates how to use the findwindow function:

  

Tchar szclassname [] = _ text ("My WND class ");

Tchar szwndname [] = _ text ("My WND ");

Hwnd = findwindow (szclassname, szwndname );

  

If (hwnd ){

MessageBox (null, _ text ("another instance is already running."), _ text ("information "),

Mb_ OK | mb_iconinformation );

}

  

It is important to note that each instance of the program has a different window name. If you call findwindow as follows

Hwnd = findwindow (szclassname, null );

Find all windows and match the window class names. If you can ensure that your window class names are unique, you can trust findwindow. Otherwise, you need a better method.

  

Method 2

  

By sharing data segments between EXE files and sharing data, you can determine whether another instance of the program exists.

Each EXE or DLL is composed of a collection of segments. in Win32 programs, each segment starts with a vertex. For example, when the compiled program is a compiler, all the code is put into. text Segment, put all uninitialized data. BSS segment, put all initialized data. data Segment.

  

You can assign one or more attributes to each segment (the following are common segment attributes ):

  

Read data in read segments

Data in the write segment can be written.

Data in the shared block can be shared by multiple instances.

Data in the execute segment can be executed

  

You can use the following command to generate segments:

# Pragma data_seg ("shared ")

Static long g_linstancecount =-1;

# Pragma data_seg ()

  

The compiler generates a new segment when generating this code, and puts the initialization data of the # pragma data_seg ("shared") Directive to the new segment shared, and uninitialized data to the. BSS segment. # Put the data after Pragma data_seg () into the default data segment.

  

It is not enough to tell the compiler to share specific data into its own segments, but also to tell the linker to share variables within a specific segment. You can specify the attribute of this segment during the link.

/Section: shared, RWS

Segment name attribute

  

During program initialization, for example, when the winmain function is called, The interlockedincrement function is called to add 1 to the variable in the shared segment. You can judge that several instances of a program are running by judging the value of the variable in the shared segment. The following code demonstrates how to determine that a running program instance is the first instance of the program.

  

Bool bisfirstinstance = (interlockedincrement (& g_linstancecount) = 0 );

If (! Bisfirstinstance ){

MessageBox (null, _ text ("Screen Saver launcher is already running."), g_szappname,

Mb_ OK | mb_iconinformation );

}

  

Add 1 to the variable in the shared segment without g_linstancecount ++. Instead, use interlockedincrement (& g_linstancecount) because the interlockedincrement function synchronizes the access to the variable (synchronize ), prevent multiple threads from accessing the same variable at the same time. For more information about thread synchronization, see Win32 SDK documentation.

There are many ways to disable multiple Win32 instances, such as Win32 core objects (mutex, semaphore) and Global atoms, here we will only briefly introduce the above two methods.

  

3. Screen Saver launch:

Screen Saver is a standard Windows executable program with the SCR extension. When editing the list of available Screen Saver programs, the control panel desktop applet searches for Windows-based executable programs with the SCR extension in the Windows startup directory (Windows directory and system directory, if a screen saver with the same file name exists in both the Windows directory and the system directory, the one in the Windows directory is ignored. Windows 95 ignores any deliberate disruption (such as changing the extension of a text file or DoS-based executable file to SCR), but changes the extension of a standard Windows executable program to SCR, windows 95 and NT will not be noticed. This is just an extreme situation. I believe users will not use this method to "test" your windows.

The standard Win32-based screen saver must follow strict standards. For more information, see the Win32 SDK documentation. One thing to mention here is that all Win32-based screen saver requires a description string of no more than 25 characters. In the resource string table of the screen saver, this indicates that the string ID must be 1.

However, we found that the screen saver in Windows 95 is not exactly written in accordance with the standards. When editing the list of available Screen Saver programs, the control panel desktop applet simply adds the name of the screen saver to the list, rather than adding the description string mentioned above. In Windows NT, the system strictly distinguishes between standard and non-standard screen saver. For standard screen saver, the system obtains 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.

The list of Screen Saver programs in Windows 95 and Windows NT is slightly different. For the sake of distinction, sslaunch in Windows 95 is represented by sslaunch95, while sslaunch in Windows NT is represented by sslaunchnt.

Sslaunch95 uses window 95 to call the screen saver, searches for the screen saver in the startup directory of Windows 95, and adds the file name to the context menu of the taskbar notification area icon, click the mouse to start the screen saver. Windows 95 saves the selected screen saver name in the/boot/SCRNSAVE. EXE file of system. ini. Sslaunch95 compares the selected screen saver name and the searched Screen Saver name saved by the system. If they are the same, set the check flag in the corresponding menu item in the context menu of the icon in the taskbar notification area, to indicate whether the Screen Saver is selected by the current user. Sslaunch95 does not determine whether the screen saver in the Windows startup directory is a real screen saver, windows 95 Win32 cannot easily determine whether an scr file is a Windows Executable File Based on GDI (ne or PE format ). The author found two functions used to determine the file type: shgetfileinfo and getbinarytype. Shgetfileinfocan export. EXE ,. com ,. BAT file types, but think. the scr file is not an executable file; getbinarytype can easily determine the file type, but Windows 95 does not support it, but simply returns error_not_implement, while Win32 supports it.

Click

Sslaunch95 can also be run in Windows NT. However, the pop-up context menu cannot use the screen saver to indicate string filling, and it cannot determine whether the SCR is a Windows executable program based on GDI.

The following describes how sslaunchnt identifies SCR files in Windows NT and how to obtain the screen saver description string from scr file resources.

A. Identify the scr file

Windows NT supports the getbinarytype function. Therefore, you can use this function to determine whether an scr file is a Windows executable program and whether it is an executable program based on Win16 or Win32. This is important because, for Win32-based SCR files, we need to obtain an important information in its string resources and the description string of the screen saver. It should also be noted that lpapplicationname should provide a full path. Otherwise, it only searches for files in the path where the process is located, which will lead to errors and thus cannot return files in the Windows startup directory. scr file information.

  

Bool getbinarytype (

Lptstr lpapplicationname,

Lpdword lpbinarytype

);

After the getbinarytype call is successful, the DWORD indicated by lpbinarytype returns the following values:

Scs_32bit_binary Win32-based application

Scs_dos_binary MS-DOS-based application

Scs_os216_binary applications based on 16-bit OS/2

The PIF file of the scs_pif_binary MS-DOS Application

Scs_posix_binary POSIX-based applications

Scs_wow_binary is a 16-bit windows application.

B. Obtain the description string of the screen saver file from the scr file string resource.

After determining a Win32-based scr file, we can start to obtain its string. In Win32, there is a simple and effective method: load an EXE or DLL file as a data file and call the LoadLibraryEx function.

Hinstance LoadLibraryEx (

Lpctstr lplibfilename, // EXE or DLL file name

Handle hfile, // reserved parameter, must be null

DWORD dwflags // function entry flag

);

Dwflags can be a combination of 0 or below:

The dont_resolve_dll_references 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 without calling the dllmain function. To obtain resources in the EXE, you can also use the LoadLibraryEx function to map the EXE to the process address space.

Load_with_altered_search_path will change the method used by LoadLibraryEx to locate the DLL file.

  

When LoadLibraryEx is called as load_library_as_datafile, the system simply creates a file image object, maps DLL (exe) to the address space of the process, and does not call dllmain (winmain ). If the call is successful, the function returns an hinstance, that is, the load address of the DLL (exe) mapped to the address space of the current process. In this way, you can call the loadstring function from the DLL (exe) obtain the specified string from the string resource table of the file.

Click

It is worth noting that it is necessary to determine whether the loadstring function call is successful, because some SCR files (even Win32-based) it may also be non-standard (for example, most SCR files in Windows 95). If loadstring fails to be called, sslaunchnt replaces the SCR description string with the file name to fill in the menu item of the sslaunchnt context menu.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.