// TWL.CPP /* * Tiny, Terminal or Toy Windows Library * Steve Donovan, Miningtek 1998 * based on SWL, 1995. */ //#define WIN32_LEAN_AND_MEAN #define NO_STRICT #include #ifdef _WIN32 //# include //# define COMMCTRL # define LOW_WORD LOWORD #else # define LOW_WORD WORD # define GWL_USERDATA 0 #endif #include #include #include #include "twl.h" #define MAX_CMD_LINE 120 #define N_CMD_LINE 20 // *hack 1.2.8 make the window class distinct from YAWL; // in general, it should be unique per process. #define EW_CLASSNAME "EVNTWNDCLSS0" #define POP_WNDCLSS "WNDCLSS" static HINSTANCE hInst; static int CmdShow; static HANDLE hAccel=0,hModeless=0; char obuff[BUFSIZE]; static char buff[MAX_CMD_LINE]; typedef unsigned char byte; // Miscelaneous functions!! long RGBF(float r, float g, float b) //------------------------------------- { return RGB(byte(255*r),byte(255*g),byte(255*b)); } long RGBI(int r, int g, int b) { return RGB(r,g,b); } int exec(pchar s, int mode, bool do_wait) //-------------------------------------- { // return WinExec(s,mode); PROCESS_INFORMATION pi; STARTUPINFO si; TWin *lastw = TWin::get_active_window(); ZeroMemory(&si,sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = mode; BOOL bRet = CreateProcess(NULL, s, NULL,NULL, // no security! FALSE, // inherited handles CREATE_NEW_CONSOLE, // creation flags NULL,NULL, &si, &pi); if (!bRet) return 0; if (do_wait) { WaitForSingleObject(pi.hProcess,1000); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } //process_id = pi.dwProcessId; lastw->set_focus(); delete lastw; return 1; } long current_time() { return GetTickCount(); } bool get_key_state(int keycode) { return GetKeyState(keycode) < 0; } int message(char *format,bool was_warning) //---------------------------------------- { //char *Args; int ret; // Args = (char *) &format + sizeof format; // vsprintf(obuff,format,Args); // ret = MessageBox(NULL,obuff,"Message",MB_ICONEXCLAMATION | MB_OKCANCEL); ret = MessageBox(NULL,format,"Message",MB_ICONEXCLAMATION | MB_OKCANCEL); if (ret == IDCANCEL) return 0; else return 1; } /// TDC /////////////// TDC::TDC() { m_hdc = m_pen = m_font = m_brush = NULL; m_twin = NULL; } TDC::~TDC() { } void TDC::get(TWin *pw) //--------------------- { if(!pw) pw = m_twin; m_hdc = GetDC(pw->handle()); } void TDC::release(TWin *pw) //-------------------------- { if(!pw) pw = m_twin; ReleaseDC(pw->handle(),m_hdc); } void TDC::kill() //-------------- { DeleteDC(m_hdc); } Handle TDC::select(Handle obj) //--------------------------- { return SelectObject(m_hdc,obj); } void TDC::select_stock(int val) //---------------------------- { select(GetStockObject(val)); } void TDC::xor_pen() //----------------- { SetROP2(m_hdc, GetROP2(m_hdc)==R2_XORPEN ? R2_COPYPEN : R2_XORPEN); } void TDC::to_logical(Point *pt, int sz) { DPtoLP(m_hdc,(LPPOINT)pt,sz); } void TDC::to_device(Point *pt, int sz) { LPtoDP(m_hdc,(LPPOINT)pt,sz); } void TDC::set_colour(long colour) { COLORREF rgb = (COLORREF)colour; get(); SetTextColor(m_hdc,rgb); if(m_pen) DeleteObject(m_pen); m_pen = CreatePen(PS_SOLID,0,rgb); select(m_pen); release(); } void TDC::set_back_colour(long colour) { COLORREF rgb = (COLORREF)colour; SetBkColor(m_hdc,rgb); if(m_brush) DeleteObject(m_brush); m_brush = CreateSolidBrush(rgb); select(m_brush); } // this changes both the _pen_ and the _text_ colour void TDC::set_colour(float r, float g, float b) //---------------------------- { set_colour(RGBF(r,g,b)); } void TDC::set_back_colour(float r, float g, float b) { set_back_colour(RGBF(r,g,b)); } void TDC::set_text_colour(long colour) { SetTextColor(m_hdc,colour); } void TDC::set_text_align(int flags, bool update_cp) //------------------------------------------------- { get(); SetTextAlign(m_hdc, flags | (update_cp ? TA_UPDATECP : 0)); release(); } void TDC::get_text_extent(pchar text, int& w, int& h, TFont *font) //---------------------------------------------------------------- { SIZE sz; HFONT oldfont; get(); if (font) oldfont = select(*font); #ifdef _WIN32 GetTextExtentPoint32(m_hdc,text,lstrlen(text),&sz); #else DWORD res = GetTextExtent(m_hdc,text,lstrlen(text)); sz.cx = LOWORD(res); sz.cy = HIWORD(res); #endif if (font) select(oldfont); release(); w = sz.cx; h = sz.cy; } // wrappers around common graphics calls void TDC::draw_text(pchar msg) //--------------------------------------------------- { TextOut(m_hdc,0,0,msg,lstrlen(msg)); } void TDC::text_out(int x, int y, char *buff, int sz) { TextOut(m_hdc,x,y,buff,sz); } void TDC::move_to(int x, int y) //---------------------------- { MoveToEx(m_hdc,x,y,NULL); } void TDC::line_to(int x, int y) //----------------------------- { LineTo(m_hdc,x,y/*,NULL*/); } void TDC::rectangle(const Rect& rt) //--------------------------------- { Rectangle(m_hdc, rt.left,rt.top,rt.right,rt.bottom); } void TDC::ellipse(const Rect& rt) //--------------------------------- { Ellipse(m_hdc, rt.left,rt.top,rt.right,rt.bottom); } void TDC::invert_rect(const Rect& rt) //----------------------------------- { InvertRect(m_hdc,(RECT *)&rt); } TClientDC::TClientDC(TEventWindow *ew) { set_hdc(ew->get_dc()->get_hdc()); set_twin(ew); get(); } TClientDC::~TClientDC() { release(); } //// TGDIObj void TGDIObj::destroy() //--------------- { if (m_hand) DeleteObject(m_hand); m_hand = NULL; } //// TFont //////// #define PLF ((LOGFONT *)m_pfont) TFont::TFont() { m_pfont = (void *) new LOGFONT; } TFont::~TFont() { delete (LOGFONT *) m_pfont; } void TFont::set(pchar spec, int sz, int ftype) //------------------------------------------- { LOGFONT&lf = *(LOGFONT *)m_pfont; // define an alias... int wt = FW_NORMAL; lf.lfHeight = sz; if (ftype & BOLD) wt = FW_BOLD; lf.lfWeight = wt; lf.lfItalic = (ftype & ITALIC) ? TRUE: FALSE; lf.lfOutPrecision = OUT_DEFAULT_PRECIS; lf.lfCharSet = ANSI_CHARSET; lf.lfQuality = PROOF_QUALITY; lf.lfEscapement = 0; lf.lfOrientation = 0; lf.lfUnderline = 0; lf.lfStrikeOut = 0; lstrcpy(lf.lfFaceName,spec); create(); } /// copy constructor TFont& TFont::operator = (const TFont& f) //-------------------------------------- { memcpy(m_pfont,f.m_pfont,sizeof(LOGFONT)); create(); return *this; } void TFont::create() //------------------ { destroy(); m_hand = CreateFontIndirect((LOGFONT *)m_pfont); } void TFont::set_name(pchar name) //------------------------------- { lstrcpy(PLF->lfFaceName,name); create(); } void TFont::set_size(int pts) //---------------------------- { PLF->lfHeight = pts; create(); } void TFont::set_bold() //----------------------- { PLF->lfWeight = FW_BOLD; create(); } void TFont::set_italic() //----------------------- { PLF->lfItalic = TRUE; create(); } ////// TWin /////////// static void check_error() { LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); // Process any inserts in lpMsgBuf. // ...(?) // Display the string. MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION ); // Free the buffer. LocalFree( lpMsgBuf ); } TWin::TWin(TWin *parent, pchar winclss, pchar text, int id, dword styleEx) //------------------------------------------------------------------------ { DWORD style = WS_CHILD | WS_VISIBLE | styleEx; HWND hwndChild = CreateWindowEx(WS_EX_LEFT,winclss,text,style, 0,0,CW_USEDEFAULT,CW_USEDEFAULT, parent->m_hwnd, (HMENU)id, hInst,NULL); set(hwndChild); check_error(); } void TWin::update() //----------------- { UpdateWindow(m_hwnd); } static inline bool as_bool(int val) { return val ? true : false; } static inline bool as_bool(void *ptr) { return ptr ? true : false; } bool TWin::is_visible() { return as_bool(IsWindowVisible(m_hwnd)); } void TWin::invalidate(Rect *lprt) { InvalidateRect(m_hwnd,(LPRECT)lprt,TRUE); } void TWin::get_rect(Rect &rt) //--------------------------- { GetWindowRect(m_hwnd,(LPRECT)&rt); } void TWin::get_client_rect(Rect &rt) { GetClientRect(m_hwnd,(LPRECT)&rt); } Point TWin::to_screen(Point pt) { ClientToScreen(m_hwnd,(LPPOINT)&pt); return pt; } Point TWin::to_client(Point pt) { ScreenToClient(m_hwnd,(LPPOINT)&pt); return pt; } int TWin::width() //--------------- { Rect rt; get_rect(rt); return rt.right - rt.left; } int TWin::height() //---------------- { Rect rt; get_rect(rt); return rt.bottom - rt.top; } void TWin::set_text(pchar str) //--------------------------- { SetWindowText(m_hwnd, str); } pchar TWin::get_text(pchar str, int sz) //------------------------------------- { GetWindowText(m_hwnd,str,sz); return str; } // These guys work with the specified _child_ of the window void TWin::set_text(int id, pchar str) //------------------------------------- { SetDlgItemText(m_hwnd,id,str); } void TWin::set_int(int id, int val) //------------------------------------- { SetDlgItemInt(m_hwnd,id,val,TRUE); } pchar TWin::get_text(int id, pchar str, int sz) //-------------------------------------------- { GetDlgItemText(m_hwnd,id,str,sz); return str; } void TWin::scroll(int dx, int dy) { ScrollWindow(m_hwnd,dx,dy,NULL,NULL); } int TWin::get_int(int id) //----------------------- { BOOL success; return (int)GetDlgItemInt(m_hwnd,id,&success,TRUE); } TWin * TWin::get_twin(int id) //-------------------- { HWND hwnd = GetDlgItem(m_hwnd,id); if (hwnd) { // Extract the 'this' pointer, if it exists TWin *pwin = (TWin *)GetWindowLong(hwnd,0); // if not, then just wrap up the handle if (!pwin) pwin = new TWin(hwnd); return pwin; } else return NULL; } TWin * TWin::get_active_window() { return new TWin(GetActiveWindow()); } void TWin::set_focus() { SetFocus((HWND)m_hwnd); } int TWin::get_id() //------------ { return GetWindowLong(m_hwnd,GWL_ID); } void TWin::close() { DestroyWindow(m_hwnd); } void TWin::resize(int x0, int y0, int w, int h) //-------------------------------------------- { MoveWindow(m_hwnd,x0,y0,w,h,TRUE); //*SJD* This is a hack to ensure that WCON child console // windows do indeed appear on the top on Win95 systems. on_top(); } void TWin::on_top() // *add 0.9.4 { SetWindowPos(handle(),HWND_TOP,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); } void TWin::resize(int w, int h) //------------------------------ { SetWindowPos(handle(),NULL,0,0,w,h,SWP_NOMOVE); } void TWin::move(int x0, int y0) //------------------------------ { SetWindowPos(handle(),NULL,x0,y0,0,0,SWP_NOSIZE); } void TWin::show(int how) //-------------------------------- { ShowWindow(m_hwnd,how); } void TWin::set_style(dword s) //--------------------------- { SetWindowLong(m_hwnd,GWL_STYLE,s); } int TWin::send_msg(int msg, int wparam, int lparam) const //--------------------------------------------------- { return SendMessage(m_hwnd, msg, wparam, lparam); } int TWin::post_msg(int msg, int wparam, int lparam) const { return PostMessage(m_hwnd, msg, wparam, lparam); } TWin *TWin::create_child(pchar winclss, pchar text, int id, dword styleEx) //------------------------------------------------------------------------ { return new TWin(this,winclss,text,id,styleEx); } int TWin::message(char *msg, int type) //------------------------------------- { int flags; char *title; if (type == MSG_ERROR) { flags = MB_ICONERROR | MB_OK; title = "Error"; } else if (type == MSG_WARNING) { flags = MB_ICONEXCLAMATION | MB_OKCANCEL; title = "Warning"; } else { flags = MB_OK; title = "Message"; } return MessageBox(m_hwnd, msg, title,flags); } TScrollBar::TScrollBar(Handle hwnd, int type) : TWin(hwnd),m_type(type) { } void TScrollBar::set_range(int rmin, int rmax, bool repaint/*=false*/) { SetScrollRange(m_hwnd,m_type,rmin,rmax,repaint); } void TScrollBar::set_pos(int rpos, bool repaint/*=false*/) { SetScrollPos(m_hwnd,m_type,rpos,repaint); } int TScrollBar::get_pos() { return GetScrollPos(m_hwnd,m_type); } //----TEventWindow class member definitions--------------------- TEventWindow::TEventWindow(pchar caption, TWin *parent, dword style) //----------------------------------------------------------------- { set_defaults(); if (style) m_style |= style; create_window(caption, parent); get_dc()->set_text_align(TA_TOP | TA_LEFT); enable_resize(true); } TEventWindow::~TEventWindow() { if (m_timer) kill_timer(); if (m_dc) delete m_dc; DestroyWindow((HWND)m_hwnd); } void TEventWindow::pre_create() {} void TEventWindow::vert_scroll() { m_sb_vert = (TScrollBar *)this; // just to flag! } void TEventWindow::create_window(pchar caption, TWin *parent) //------------------------------------------------------------------- { HWND hParent; void *CreatParms[2]; pre_create(); m_dc = new TDC; CreatParms[0] = (void *)this; if (parent) hParent = parent->handle(); else hParent = NULL; m_hwnd = CreateWindow (EW_CLASSNAME, caption, m_style, CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT, hParent,NULL, hInst, CreatParms); if(m_style & WS_VSCROLL) m_sb_vert = new TScrollBar(m_hwnd,SB_VERT); set_window(); } void TEventWindow::set_defaults() //------------------------------- { m_style = WS_OVERLAPPEDWINDOW | CS_DBLCLKS; m_bkgnd_brush = GetStockObject (WHITE_BRUSH /*LTGRAY_BRUSH*/); m_bk_color = RGB(192,192,192); m_hmenu = NULL; m_timer = 0; m_dispatcher = NULL; m_dc = NULL; m_bail_out = false; m_sb_vert = NULL; } void TEventWindow::add_handler(AbstractMessageHandler *m_hand) { if (!m_dispatcher) m_dispatcher = m_hand; else m_dispatcher->add_handler(m_hand); } void TEventWindow::update_data() { get_handler()->write(); } void TEventWindow::update_controls() { get_handler()->read(); } bool TEventWindow::cant_resize() { return !m_do_resize; } int TEventWindow::metrics(int ntype) //---------------------------------- // Encapsulates what we need from GetSystemMetrics() and GetTextMetrics() { if (ntype < TM_CAPTION_HEIGHT) { // text metrics TEXTMETRIC tm; GetTextMetrics(get_dc()->get_hdc(),&tm); if (ntype == TM_CHAR_HEIGHT) return tm.tmHeight; else if (ntype == TM_CHAR_WIDTH) return tm.tmMaxCharWidth; } else { switch(ntype) { case TM_CAPTION_HEIGHT: return GetSystemMetrics(SM_CYMINIMIZED); case TM_MENU_HEIGHT: return GetSystemMetrics(SM_CYMENU); case TM_CLIENT_EXTRA: return metrics(TM_CAPTION_HEIGHT) + (m_hmenu != NULL) ? metrics(TM_MENU_HEIGHT) : 0; case TM_SCREEN_WIDTH: return GetSystemMetrics(SM_CXMAXIMIZED); case TM_SCREEN_HEIGHT: return GetSystemMetrics(SM_CYMAXIMIZED); default: return 0; } } return 0; } void TEventWindow::client_resize(int cwidth, int cheight) { // *SJD* This allows for menus etc - really is a frame window method?? resize(cwidth,cheight + metrics(TM_CLIENT_EXTRA)); } void TEventWindow::enable_resize(bool do_resize, int w, int h) { m_do_resize = do_resize; m_fixed_size.x = w; m_fixed_size.y = h; } POINT TEventWindow::fixed_size() { return m_fixed_size; } void TEventWindow::cursor(CursorType curs) { HCURSOR new_cursor; if (curs == RESTORE) new_cursor = m_old_cursor; else switch(curs) { case HOURGLASS: new_cursor = LoadCursor(NULL,IDC_WAIT); break; } SetCursor(new_cursor); } void TEventWindow::set_window() //----------------------------- { set(m_hwnd); // set_win(*this); //...set up DC part.....?? } void TEventWindow::set_background(float r, float g, float b) //----------------------------------------- { COLORREF rgb = RGBF(r,g,b); m_bkgnd_brush = CreateSolidBrush(rgb); get_dc()->get(this); SetBkColor(get_dc()->get_hdc(),rgb); get_dc()->select(m_bkgnd_brush); m_bk_color = rgb; get_dc()->release(this); invalidate(); } void TEventWindow::set_menu(char *res) //------------------------------------ { if (m_hmenu) DeleteObject(m_hmenu); set_menu(LoadMenu(hInst,res)); } void TEventWindow::set_menu(Handle menu) //------------------------------------ { m_hmenu = menu; SetMenu(m_hwnd,menu); } void TEventWindow::check_menu(int id, bool check) { CheckMenuItem(m_hmenu,id, MF_BYCOMMAND | (check ? MF_CHECKED : MF_UNCHECKED)); } void TEventWindow::show(int cmd_show) //----------------------------------- { // default: use the 'nCmdShow' we were _originally_ passed if (! cmd_show) cmd_show = CmdShow; ShowWindow(m_hwnd,cmd_show); } void TEventWindow::create_timer(int msec) //--------------------------------------- { if(m_timer) kill_timer(); m_timer = SetTimer(m_hwnd,1,msec,NULL); } void TEventWindow::kill_timer() //----------------------------- { KillTimer(m_hwnd, m_timer); } // *fix 1.2.2 (Eric) We were spending an excessive amount of time doing idle processing #ifdef BUILD_WITH_GTK void special_idle(); // in UCW_GTK #else void special_idle() { WaitMessage(); } #endif // Message Loop! // *NB* this loop shd cover ALL cases, controlled by global // variables like mdi_sysaccell, accell, hModelessDlg, etc. // 31/08/00 - there's a bail out flag - not perhaps the // most elegant method, but it'll do. int TEventWindow::run() //--------------------- { MSG msg; while (TRUE) { if (PeekMessage (&msg, NULL, 0, 0,PM_REMOVE)) { if (msg.message == WM_QUIT) break; if (m_bail_out) { m_bail_out = false; return -1; } if (! hAccel || !TranslateAccelerator(m_hwnd,hAccel,&msg)) { if (! hModeless || !IsDialogMessage(hModeless,&msg)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } } } else special_idle(); } return msg.wParam ; } static unsigned long mMainThread; void set_main_thread(unsigned long id) { mMainThread = id; // GetCurrentThreadId(); } void TEventWindow::quit_loop() { m_bail_out = true; //post_msg(WM_CHAR,' ',1); ULONG id = GetWindowThreadProcessId((HWND)handle(),NULL); BOOL res = PostThreadMessage(id,WM_CHAR,' ',1); } // Place holder functions - no functionality offered at this level! void TEventWindow::size(int,int) {} void TEventWindow::on_move() {} bool TEventWindow::command(int) { return true; } bool TEventWindow::sys_command(int) { return false; } void TEventWindow::paint(TDC&) {} void TEventWindow::mouse_down(Point&) {} void TEventWindow::mouse_up(Point&) { } void TEventWindow::right_mouse_down(Point&) {} void TEventWindow::mouse_move(Point&) { } void TEventWindow::mouse_double_click(Point& pt) { } void TEventWindow::focus(bool) {} void TEventWindow::keydown(int) { } void TEventWindow::on_char(int,int) { } void TEventWindow::destroy() { } void TEventWindow::timer() { } void TEventWindow::vscroll(int code, int posn) { } int TEventWindow::handle_user(long lparam, long wparam) { return 0; } ////// Members of TFrameWindow TFrameWindow::TFrameWindow(pchar caption, TWin *cli, int style, TWin *parent) : TEventWindow(caption,parent,style) { // int SBParts[2]; set_client(cli); #ifdef COMMCTRL /* m_status = CreateStatusWindow(WS_CHILD | WS_BORDER | WS_VISIBLE, "", m_hwnd, 1); if(!m_status) set_text("no status"); SBParts[0] = width()/2; SBParts[1] = -1; SendMessage(m_status,SB_SETPARTS,2,(LPARAM)SBParts); */ m_status = NULL; // for now!! #else m_status = NULL; #endif } TFrameWindow::~TFrameWindow() { delete m_client; } void TFrameWindow::set_status_text(int id, pchar txt) { #ifdef COMMCTRL SendMessage(m_status,SB_SETTEXT,id,(LPARAM)txt); #endif } void TFrameWindow::destroy() //....overrides the default w/ application-closing behaviour!! { PostQuitMessage(0); } void TFrameWindow::set_client(TWin *cli) { m_client = cli; if (m_client) { m_client->show(); } } void TFrameWindow::size() { RECT rt; HDWP hdwp; int n = 0, bottom_extra = 0; if (m_status) n++; if (m_client) n++; if (n==0) return; GetClientRect(m_hwnd,&rt); hdwp = BeginDeferWindowPos(n); if (m_status) { DeferWindowPos(hdwp,m_status,NULL,0,0, //??? rt.right - rt.left, 20, SWP_NOZORDER); bottom_extra = 20; } if (m_client) DeferWindowPos(hdwp,m_client->handle(),NULL,0,0, rt.right - rt.left, rt.bottom-rt.top - bottom_extra, SWP_NOZORDER | SWP_NOMOVE); EndDeferWindowPos(hdwp); } /// Windows controls - TControl //////////// TControl::TControl(TWin *parent, pchar classname, pchar text,int id, long style) : TEventWindow(parent,classname,text,id,style) { m_colour = RGB(0,0,0); //RGB(255,255,255); // shd depend on background! m_font = NULL; SetWindowLong(m_hwnd,-21 /*GWL_USERDATA*/,(long)this); m_parent = (TEventWindow *)parent; //calc_size(); } TControl::~TControl() { } TControl * TControl::user_data(Handle handle) { return (TControl *)GetWindowLong(handle,-21 /*GWL_USERDATA*/); } void TControl::calc_size() { int cx,cy; m_parent->get_dc()->get_text_extent(get_text(),cx,cy,m_font); resize(int(1.05*cx),int(1.05*cy)); } bool TControl::is_type(char *tname) { return strcmp(type_name(),tname)==0; } void TControl::set_font(TFont *fnt) { m_font = fnt; calc_size(); if (m_font) send_msg(WM_SETFONT,(WPARAM)m_font->handle(),(LPARAM)TRUE); } void TControl::set_colour(float r, float g, float b) { m_colour = (long)RGBF(r,g,b); update(); } TLabel::TLabel(TWin *parent, pchar text, int id) //-------------------------------------- : TControl(parent,"STATIC",text,id,0x0) { } TEdit::TEdit(TWin *parent, pchar text, int id, long style) //----------------------------------------------- : TControl(parent,"EDIT",text,id,style | WS_BORDER) { } //-----------------Dialog boxes-------------------------- TDialog::~TDialog () { FreeProcInstance((DLGPROC)m_lpfnBox); } bool TDialog::was_successful() { if (modeless()) return as_bool(handle()); else return as_bool(m_ret); } DLGFN DialogProc (HWND hdlg, UINT msg, UINT wParam,LONG lParam); void TDialog::go () //----------------- { HWND hdlg,hOwner; hOwner = (m_owner) ? m_owner->handle() : NULL; //GetDesktopWindow(); m_lpfnBox = (void FAR *)MakeProcInstance((FARPROC)DialogProc,hInst); if (modeless()) { hdlg = CreateDialogParam(hInst,m_name,hOwner,(DLGPROC)m_lpfnBox,(long)this); hModeless = hdlg; } else { m_ret = DialogBoxParam(hInst,m_name,hOwner,(DLGPROC)m_lpfnBox,(long)this); m_hwnd = 0; // thereafter, this object is not a valid window... } ShowWindow(hdlg,SW_SHOW); } TWin * TDialog::field(int id) { return new TWin(GetDlgItem(m_hwnd,id)); } //....Modeless Dialog Box procedure......................... DLGFN DialogProc (HWND hdlg, UINT msg, UINT wParam,LONG lParam) { int ret; TDialog *This = (TDialog *) GetWindowLong(hdlg,8/*DWL_USER*/); switch (msg) { case WM_INITDIALOG: //..... 'This' pointer passed as param from CreateDialogParam() SetWindowLong(hdlg,8/*DWL_USER*/,lParam); This = (TDialog *)lParam; if (This->modeless()) hModeless = hdlg; This->set(hdlg); return This->init(); case WM_COMMAND: switch(LOW_WORD(wParam)) { case IDOK: ret = This->finis(); if (! ret) return FALSE; // no, we're not finished yet! case IDCANCEL: if (This->modeless()) SendMessage(hdlg,WM_CLOSE,0,0L); else EndDialog(hdlg,wParam==IDOK); break; default: This->command(wParam); break; } return TRUE; case WM_CLOSE: DestroyWindow(hdlg); hModeless = 0; break; } return FALSE; // we did not process the message... } WNDFN WndProc (HWND hwnd, UINT msg, WPARAM wParam,LPARAM lParam); //----------------Window Registration---------------------- void RegisterEventWindow(HANDLE hIcon=0, HANDLE hCurs=0) //------------------------------------------------------ { WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 4; wndclass.hInstance = hInst; wndclass.hIcon = hIcon ? hIcon : LoadIcon (NULL, IDI_APPLICATION) ; wndclass.hCursor = hCurs ? hCurs : LoadCursor (NULL, IDC_ARROW) ; wndclass.hbrBackground = NULL; //GetStockObject(LTGRAY_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = EW_CLASSNAME; RegisterClass (&wndclass); } char *args[N_CMD_LINE]; int n_args; int ParseCmdLine(LPSTR CmdLine, char **args); int get_argc() { return n_args; } char **get_argv() { return args; } int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) //---------------------------------------------------------------- { #ifdef COMMCTRL InitCommonControls(); #endif hInst = hInstance; CmdShow = nCmdShow; n_args = ParseCmdLine(lpszCmdLine, args); if (! hPrevInstance) RegisterEventWindow(); return SMain(n_args,args); } //--------------Default Window Proc for EventWindow----------------- typedef void *PVOID; WNDFN WndProc (HWND hwnd, UINT msg, WPARAM wParam,LPARAM lParam) //---------------------------------------------------------------------------- { // static SWin w; static BOOL dragging = FALSE; static long MouseTime = 0; static UINT size_flags; LPMINMAXINFO pSizeInfo; long ret; TEventWindow *This = (TEventWindow *) GetWindowLong(hwnd,0); switch (msg) { case WM_CREATE: { LPCREATESTRUCT lpCreat = (LPCREATESTRUCT) lParam; PVOID *lpUser; lpUser = (PVOID *)lpCreat->lpCreateParams; //..... 'This' pointer passed as first word of creation parms SetWindowLong(hwnd,0,(long)lpUser[0]); This = (TEventWindow *)lpUser[0]; This->get_dc()->set_twin(This); } return 0; case WM_SIZE: This->size(LOWORD(lParam),HIWORD(lParam)); return 0; case WM_MOVE: This->on_move(); return 0; case WM_GETMINMAXINFO: if (This && This->cant_resize()) { pSizeInfo = (LPMINMAXINFO) lParam; pSizeInfo->ptMaxTrackSize = This->fixed_size(); pSizeInfo->ptMinTrackSize = This->fixed_size(); } return 0; // case WM_COMMAND: if (This->m_dispatcher) { This->m_dispatcher->dispatch(LOW_WORD(wParam),HIWORD(wParam),(Handle)lParam); return 0; } if (This->command(LOW_WORD(wParam))) return 0; else break; case WM_USER_PLUS: return This->handle_user(wParam,lParam); case WM_KEYDOWN: This->keydown(wParam); return 0; case WM_CHAR: This->on_char(wParam,LOWORD(lParam)); // 1 return 0; case WM_HSCROLL: if (This->m_dispatcher) { int id = GetWindowLong((HWND)lParam,GWL_ID); This->m_dispatcher->dispatch(id,LOWORD(wParam),(Handle)lParam); } return 0; case WM_VSCROLL: This->vscroll(wParam,This->scroll_bar()->get_pos()); return 0; case WM_PAINT: { PAINTSTRUCT ps; TDC *dc = This->get_dc(); dc->set_hdc(BeginPaint(hwnd,&ps)); This->paint(*dc); dc->set_hdc(NULL); EndPaint(hwnd,&ps); } return 0; // Mouse messages.... case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_RBUTTONDOWN: case WM_LBUTTONDBLCLK: { Point pt(LOWORD(lParam),HIWORD(lParam)); //pt.to_logical(*This); switch (msg) { case WM_LBUTTONDOWN: This->mouse_down(pt); break; case WM_LBUTTONUP: This->mouse_up(pt); break; case WM_RBUTTONDOWN: This->right_mouse_down(pt); break; case WM_LBUTTONDBLCLK: This->mouse_double_click(pt); break; } } return 0; case WM_MOUSEMOVE: // needs different treatment?? { Point pt(LOWORD(lParam),HIWORD(lParam)); This->mouse_move(pt); } return 0; case WM_ERASEBKGND: { RECT rt; GetClientRect(hwnd,&rt); FillRect((HDC)wParam,(LPRECT)&rt, This->m_bkgnd_brush); } return 0; #ifdef _WIN32 case WM_CTLCOLORSTATIC: { TControl *ctl = (TControl *)GetWindowLong((HWND)lParam,-21 /*GWL_USERDATA*/); SetBkColor((HDC)wParam, (COLORREF)This->m_bk_color); SetTextColor((HDC)wParam, ctl->get_colour()); } return (long)This->m_bkgnd_brush; #endif case WM_SETFOCUS: This->focus(true); return 0; case WM_KILLFOCUS: This->focus(false); return 0; case WM_SYSCOMMAND: if (This->sys_command(LOW_WORD(wParam))) return 0; //? else break; case WM_TIMER: This->timer(); return 0; case WM_CLOSE: if (! This->query_close()) return 0; break; // *NOTE* this was not here!! case WM_DESTROY: //*fix 1.2.8 This had been commented out; prevents closing via usual window operation. This->destroy(); if (This->m_hmenu) DeleteObject(This->m_hmenu); // but why here? return 0 ; } ret = DefWindowProc (hwnd , msg, wParam, lParam) ; return ret; } char *_quote_strtok(char *str, char str_delim) { // a specialized version of strtok() which treats quoted strings specially // (used for handling command-line parms) static char *tok; if(str != NULL) tok = str; while (*tok && isspace(*tok)) tok++; if (*tok == '\0') return NULL; if (*tok == str_delim) { tok++; // skip " str = tok; while (*tok && *tok != str_delim) tok++; } else { str = tok; while (*tok && ! isspace(*tok)) tok++; } if (*tok) *tok++ = '\0'; return str; } int ParseCmdLine(LPSTR CmdLine, char **args) //----------------------------------------- { int i; char *arg; static char app_path[255]; GetModuleFileName(NULL,app_path,255); lstrcpy(buff,CmdLine); args[0] = app_path; args[1] = _quote_strtok(buff,'\"'); if (! args[1]) return 1; // at least one argument! i = 2; while (arg = _quote_strtok(NULL,'\"')) args[i++] = arg; return i; }