27 using namespace basis;
34 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
37 const int STARTUP_MESSAGE = WM_USER + 123;
40 const int TIMER_EVENT_ID = 23;
44 struct anchor_association {
49 : _handle(wh), _anchor_object(wo) {}
52 class anchor_association_list
53 :
public array<anchor_association>,
public virtual root_object
62 SAFE_STATIC(anchor_association_list, associations, )
91 for (
int i = 0; i < associations().length(); i++) {
92 if (associations()[i]._handle == _wind_handle) {
93 associations().zap(i, i);
113 bool to_return =
false;
114 for (
int i = 0; i < associations().length(); i++) {
118 if (ret) to_return =
true;
152 #ifdef DEBUG_PROCESS_MANAGER
159 #ifdef DEBUG_PROCESS_MANAGER
160 LOG(
astring(astring::SPRINTF,
"found window %lx", win_found));
163 LOG(
astring(
"Failed to find special window for [") + app_name
174 LOG(
astring(
"Failed to send close message to [") + app_name
181 #ifdef DEBUG_PROCESS_MANAGER
182 LOG(
"graceful shutdown not implemented for this OS.");
191 const astring &app_name,
int cycle)
198 if (_wind_handle)
return true;
200 _instance = instance;
202 *_anchor_title = make_well_known_title(app_name);
203 *_anchor_class = make_well_known_class(app_name);
204 _class_reg = register_class();
205 _wind_handle = CreateWindow(to_unicode_temp(*_anchor_class),
206 to_unicode_temp(*_anchor_title), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
208 if (!_wind_handle)
return false;
210 register_anchor(_wind_handle);
211 ShowWindow(_wind_handle, SW_HIDE);
212 UpdateWindow(_wind_handle);
213 PostMessage(_wind_handle, STARTUP_MESSAGE, 0, 0);
222 associations() += anchor_association(wind,
this);
229 ATOM process_anchor::register_class()
233 wcex.cbSize =
sizeof(WNDCLASSEX);
235 wcex.style = CS_HREDRAW | CS_VREDRAW;
236 wcex.lpfnWndProc = (WNDPROC)WndProc;
239 wcex.hInstance = _instance;
241 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
242 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
244 to_unicode_persist(hold_class, _anchor_class->s());
245 wcex.lpszClassName = hold_class;
248 return RegisterClassEx(&wcex);
253 LRESULT CALLBACK process_anchor::WndProc(HWND hWnd, UINT message,
254 WPARAM wParam, LPARAM lParam)
257 case STARTUP_MESSAGE: {
258 for (
int i = 0; i < associations().length(); i++) {
259 if (associations()[i]._handle == hWnd) {
266 SetTimer(anch._wind_handle, TIMER_EVENT_ID, anch._cycle, 0);
273 for (
int i = 0; i < associations().length(); i++) {
274 if (associations()[i]._handle == hWnd) {
276 associations()[i]._anchor_object->handle_shutdown();
277 associations()[i]._anchor_object->set_defunct();
281 return DefWindowProc(hWnd, message, wParam, lParam);
289 bool found_window =
false;
290 for (
int i = 0; i < associations().length(); i++)
291 if (associations()[i]._handle == hWnd) {
294 KillTimer(hWnd, TIMER_EVENT_ID);
296 associations()[i]._anchor_object->handle_timer();
299 SetTimer(hWnd, TIMER_EVENT_ID,
300 associations()[i]._anchor_object->_cycle, 0);
307 to_return = DefWindowProc(hWnd, message, wParam, lParam);
312 HDC hdc = BeginPaint(hWnd, &ps);
317 default:
return DefWindowProc(hWnd, message, wParam, lParam);
326 filename app_short = application_name;
334 filename app_short = application_name;
340 const astring &application_name,
int cycle)
343 if (!win.
setup(handle, application_name, cycle))
return false;
349 msg.hwnd = 0; msg.message = 0; msg.wParam = 0; msg.lParam = 0;
351 TranslateMessage(&msg);
352 DispatchMessage(&msg);
Represents a sequential, ordered, contiguous collection of objects.
Provides a dynamically resizable ASCII character string.
Provides operations commonly needed on file names.
filename basename() const
returns the base of the filename; no directory.
Implements a graceful shutdown procedure for an application.
void set_defunct()
used by the derived class to mark that this object is about to exit.
static bool close_this_program()
causes this particular program to shut down.
bool setup(application_instance handle, const basis::astring &application_name, int timing_cycle=0)
constructs a process_anchor for the "application_name" specified.
virtual void handle_startup()
derived classes can override this to catch the application startup.
virtual void handle_timer()
invoked periodically if the anchor was setup() with a timer "cycle".
static basis::astring make_well_known_class(const basis::astring &application_name)
same as above but for the anchor's class name.
void register_anchor(window_handle anchor)
this supports the anchor being created elsewhere.
static bool launch(process_anchor &anchor, application_instance handle, const basis::astring &app, int cycle=0)
establishes a process_anchor for the program named "app".
process_anchor()
constructor does very little; setup() begins operation.
static bool close_app_anchor(const basis::astring &app_name)
closes the anchor object associated with "app_name".
bool defunct() const
returns true if the object has been marked as defunct.
static basis::astring make_well_known_title(const basis::astring &application_name)
returns the string form of the well-known window title for the process_anchor.
virtual void handle_shutdown()
invoked just prior to the shutdown of this anchor.
virtual ~process_anchor()
A platform-independent way to alert a program that it should shut down immediately.
static bool is_defunct()
returns true if the object has been marked as defunct.
static void set_defunct()
used by the derived class to mark that this object is about to exit.
bool setup(const basis::astring &app_name, int timer_period=0)
constructs a shutdown_alerter for the "app_name" specified.
static void close_this_program()
causes this particular application to begin shutting down.
static bool launch_console(shutdown_alerter &alert, const basis::astring &app_name, int timer_period=0)
this is used to begin execution of a console mode application.
static bool close_application(const basis::astring &app_name)
attempts to close the application named "app_name".
Constants and objects used throughout HOOPLE.
#define NULL_POINTER
The value representing a pointer to nothing.
#define DEFINE_CLASS_NAME(objname)
Defines the name of a class by providing a couple standard methods.
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
Implements an application lock to ensure only one is running at once.
The guards collection helps in testing preconditions and reporting errors.
void WHACK(contents *&ptr)
deletion with clearing of the pointer.
A platform independent way to obtain the timestamp of a file.
A logger that sends to the console screen using the standard output device.
A dynamic container class that holds any kind of object via pointers.
#define SAFE_STATIC(type, func_name, parms)
Statically defines a singleton object whose scope is the program's lifetime.
Support for unicode builds.
void * application_instance