From: Jimbo on 11 Jan 2010 20:08 Hello I am looking for advice on what are the proper practices when coding an application or a C++ Win32 Application & how to improve how I code applications. I have my application I have made below which just shows a map of the world & a dot on the city we are focused on. If the user clicks anywhere in the client area, the program will find the nearest city & select it & the same will happen if you press next or prev. Some things I am not sure about concerning C++ Win32 app are: - are windows messages & functions meant to be handled in Winmain or is it ok to handle them in a class. For example, if I have some code that grabs text from an edit box, is it better coding practice to place that code in WinMain or in a Class? Any advice on improving my app would be really helpful :) Especially on which functions should be part of main & which functions should be in a class. WinMain: [code] /* Application: Displays a world map & a dot at position of the city we are focused(selected) on */ #include <windows.h> #include <stdio.h> #include <cmath> #include <vector> #include <string> #include <cstdlib> #include "conWorldCoord.h" using namespace std; #define IDB_NEXT 1 #define IDB_PREV 2 #define IDT_CNAME 3 #define IDB_MAP 4 #define IDB_DOT 5 const char g_szClassName[] = "myWindowClass"; static HINSTANCE gInstance; controller control; // Functions List // LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); int WINAPI WinMain(HINSTANCE gInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wc; HWND hwnd; MSG Msg; //Step 1: Registering the Window Class wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = gInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(DKGRAY_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = g_szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); // if registration of main class fails if(!RegisterClassEx(&wc)) { MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); return 0; } // Step 2: Creating the Window hwnd = CreateWindowEx( WS_EX_CLIENTEDGE, g_szClassName, "Displays the Long & Lat of world cities", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 600, 500, NULL, NULL, gInstance, NULL); if(hwnd == NULL) { MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); return 0; } ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); // Step 3: The Message Loop while(GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam; } // Step 4: the Window Procedure LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CREATE: { // Create GUI control.createGUI (hwnd,gInstance,IDT_CNAME,IDB_PREV,IDB_NEXT,IDB_MAP,IDB_DOT); } break; case WM_PAINT: // Necessary to draw city focus dot { } break; case WM_LBUTTONDOWN: // select city closest to mouse position if not already selected if (control.setFocusCity(hwnd,IDT_CNAME,LOWORD (lParam),HIWORD(lParam))==true) { control.drawCityBmp(hwnd,IDB_MAP,IDB_DOT); // call function to draw dot on newly selected city } break; case WM_COMMAND: { switch(LOWORD(wParam)) { case IDB_NEXT: { control.setFocusCity (hwnd,IDT_CNAME,true); // advance focus to next city control.drawCityBmp (hwnd,IDB_MAP,IDB_DOT); // call function to draw dot on new city } break; case IDB_PREV: { control.setFocusCity (hwnd,IDT_CNAME,true); // set focus to previous city control.drawCityBmp (hwnd,IDB_MAP,IDB_DOT); // call function to draw dot on new city } break; default: break; } } break; case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); break; } } [/code] Header file: [code] // controller class for Windows App World Coord #ifndef CONWORLDCOORD_H #define CONWORLDCOORD_H #include <windows.h> #include <vector> #include <cstdlib> #include <string> using namespace std; struct city { string name; int x; int y; int groupPos; // index position in cityList }; class controller { public: vector <city*> cityList; // store all cities in vector controller(); void createGUI(HWND hwnd, HINSTANCE gInstance, UINT cityName, UINT butPrev, UINT butNext, UINT bmpMap, UINT bmpDot); void registerCities(); void setFocusCity(HWND hwnd, UINT cityName, bool next); bool setFocusCity(HWND hwnd, UINT cityName, int mouseX, int mouseY); void drawCityBmp(HWND hwnd, UINT bmpMapMsg, UINT bmpDotMsg); float pointDistance(int x1, int y1, int x2, int y2); city* instanceNearest(int x, int y); private: city *focusCity; // the city we are focused on now int index; // index of cityList vector HBITMAP mapImg; // handle to bitmap of world HBITMAP cityImg; // handle to bitmap of City Dot BITMAP bm; HWND stMapImg; HWND stDotImg; int xImgOffset, yImgOffset; string focus; string cityStr; string focusStr; // output/record what city we are currently focused on }; #endif [/code] Implementation file: [code] #include <windows.h> #include <vector> #include <cstdlib> #include <string> #include <cmath> #include "conWorldCoord.h" using namespace std; controller::controller() { // Constructor // Load Bitmaps - World map & dot mapImg = (HBITMAP)LoadImage(NULL,"worldMapScaled.bmp",IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE); cityImg = (HBITMAP)LoadImage(NULL,"dot.bmp",IMAGE_BITMAP,0,0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE); // if load fails if (cityImg==NULL || mapImg==NULL) { MessageBox(NULL,"Failed to load bitmaps","Error",MB_OK | MB_ICONERROR); } // get cityBmp offsets GetObject(cityImg,sizeof(bm),&bm); xImgOffset = bm.bmWidth/2; yImgOffset = bm.bmHeight/2; focus = "City Focus = "; cityStr = "New York"; // should be cityFocus->name; index = 0; registerCities(); // register cities } void controller::createGUI(HWND hwnd, HINSTANCE gInstance, UINT cityName, UINT butPrev, UINT butNext, UINT bmpMap, UINT bmpDot) { // create GUI // NB check whether we even need the UNIT msgs?? // change window x,y,xW,yH coords to Width+30 etc. HFONT hfDefault; hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT); // set font focusStr = focus+cityStr; // focusStr="City Focus = New York" HWND stCityFocus = CreateWindowEx(0,"Static",focusStr.c_str (),WS_BORDER | WS_CHILD | WS_VISIBLE | SS_CENTER, 30,400,150,16,hwnd,(HMENU) cityName,gInstance,NULL); HWND btPrev = CreateWindowEx(0,"Button","Prev",WS_BORDER | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 410,400,70,20,hwnd,(HMENU) butPrev,gInstance,NULL); HWND btNext = CreateWindowEx(0,"Button","Next",WS_BORDER | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 490,400,70,20,hwnd,(HMENU) butNext,gInstance,NULL); // draw world map & dot stMapImg = CreateWindowEx(0,"Static","",WS_CHILD | WS_VISIBLE | SS_BITMAP, 20,10,540,380,hwnd,(HMENU) bmpMap,gInstance,NULL); stDotImg = CreateWindowEx(0,"Static","",WS_CHILD | WS_VISIBLE | SS_BITMAP, 185-xImgOffset,140- yImgOffset,CW_USEDEFAULT, CW_USEDEFAULT,hwnd, (HMENU)bmpDot,gInstance,NULL); // Set window fonts SendMessage(stCityFocus,WM_SETFONT,(WPARAM)hfDefault,MAKELPARAM (FALSE, 0)); SendMessage(btPrev,WM_SETFONT,(WPARAM)hfDefault,MAKELPARAM(FALSE, 0)); SendMessage(btNext,WM_SETFONT,(WPARAM)hfDefault,MAKELPARAM(FALSE, 0)); // Display bitmaps SendMessage(stMapImg,STM_SETIMAGE,(WPARAM)IMAGE_BITMAP,(LPARAM) mapImg); SendMessage(stDotImg,STM_SETIMAGE,(WPARAM)IMAGE_BITMAP,(LPARAM) cityImg); } void controller::registerCities() { // Post: Create/Declare & define city data city *NewYork = new city; // BECAUSE I HAVE USED 'new' HERE DO i NEED TO 'delete' THEM BEFORE I CLOSE THE APPLICATION??? city *London = new city; // IF I DO CAN YOU EXPLAI HOW & WHERE I PUT THE DELETE CODE city *Sydney = new city; // store cities in global vector cityList.push_back(NewYork); // ERROR Occurs here Line 79 - 'cityList' undeclared cityList.push_back(London); cityList.push_back(Sydney); NewYork->name = "New York"; NewYork->x = 185; // should be AppWidth-150 etc. NewYork->y = 140; // should be AppHeight-250 etc. London->name = "London"; London->x = 288; London->y = 110; Sydney->name = "Sydney"; Sydney->x = 490; Sydney->y = 265; //set focus city to 1st city focusCity = cityList.at(0); // ERROR Occurs here Line 96 - 'focusCity' undeclared } void controller::setFocusCity(HWND hwnd, UINT cityName, bool next) { // Post: Sets cityFocus to next or previous city depending on bool next value // If next is true we want to advance our city focus if (next) { // make sure index is not > size of cityList vector if (index < cityList.size()-1) { index += 1; } else index = 0; } else if (!next) { // we want to focus on previous city if (index != 0) { index -= 1; } else index = cityList.size()-1; } // append which city we are now focusing on focusCity = cityList.at(index); cityStr = focusCity->name; focusStr = focus+cityStr; SetDlgItemText(hwnd,cityName,focusStr.c_str()); } bool controller::setFocusCity(HWND hwnd, UINT cityName, int mouseX, int mouseY) { // Post: finds closest city to mouse position/Coords & selects it city* nearestCity = instanceNearest(mouseX,mouseY); // if the closest city to mouse pos.. is not our focusCity(not already selected) if (nearestCity != focusCity) { focusCity = nearestCity; cityStr = focusCity->name; focusStr = focus+cityStr; SetDlgItemText(hwnd,cityName,focusStr.c_str()); return true; } else return false; } void controller::drawCityBmp(HWND hwnd, UINT bmpMapMsg, UINT bmpDotMsg) { // Post: Draw dot bmp at location of current focus city // create bmp coords by compensating for x,y offset int xPos = (focusCity->x)-xImgOffset; int yPos = (focusCity->y)-yImgOffset; // reset city dot bmp position SetWindowPos(stDotImg,HWND_TOP,xPos,yPos,CW_USEDEFAULT, CW_USEDEFAULT,SWP_ASYNCWINDOWPOS); // Redraw world map & city dot SendMessage(stMapImg,STM_SETIMAGE,(WPARAM)IMAGE_BITMAP,(LPARAM) mapImg); SendMessage(stDotImg,STM_SETIMAGE,(WPARAM)IMAGE_BITMAP,(LPARAM) cityImg); } float controller::pointDistance(int x1, int y1, int x2, int y2) { return (sqrt( ((x2-x1)*(x2-x1)) + ((y2-y1)*(y2-y1)) )); } city* controller::instanceNearest(int x, int y) { // Pre: cityList/instance count of object MUST be > 0 // Post: returns the instance closest to specified point float dist = 99999; int size = cityList.size(); for (int i=0; i<size; i++) { float myDist = pointDistance(x,y,cityList.at(i)->x,cityList.at (i)->y); if (myDist < dist) { dist = myDist; index = i; // record vector cityList index of focus } } return cityList.at(index); } [/code]
From: ScottMcP [MVP] on 11 Jan 2010 21:33 On Jan 11, 8:08 pm, Jimbo <nill...(a)yahoo.com> wrote: > Some things I am not sure about concerning C++ Win32 app are: > - are windows messages & functions meant to be handled in Winmain or > is it ok to handle them in a class. > For example, if I have some code that grabs text from an edit box, is > it better coding practice to place that code in WinMain or in a Class? > > Any advice on improving my app would be really helpful :) > Especially on which functions should be part of main & which functions > should be in a class. Your API-level code represents the way things were about 1990, before C ++ became popular. Rather than asking which functions should be in a class you should be looking at ways to work entirely in C++, and to avoid reinventing the wheel with all the mechanisms that are a standard part of any Windows GUI application. There are several popular C++ class libraries that make all this much more productive. They include Microsoft's MFC and ATL, and open source WxWidgets and Qt. Another option, which is especially relevant if you will be looking for employment, is to use C# with WinForms. Most new work in Windows GUIs is done with this option.
|
Pages: 1 Prev: Network Port Algorithms Next: Returning lots of data from DLL function |