Jump to content
  • Advertisement

Texus

Member
  • Content Count

    65
  • Joined

  • Last visited

Community Reputation

248 Neutral

About Texus

  • Rank
    Member

Personal Information

  1. Actually this doesn't immediately solve it. I would still have to put all functions from Group into the Window class and let these functions call those from the 'Desktop' object. Because without letting Window inherit from Group, it won't have Add, Remove, Copy, GlobalFont and stuff like that. These are things that every group should have, so these functions must end up being be public in both GroupObject and Window. And making the window a widget would give it some functions that aren't really usefull. As a root object, you can't have siblings thus functions like MoveToBack and MoveToFront don't make much sense. And those aren't the only functions from Object that wouldn't mean much.
  2. Thanks for taking the time to look into this. The name might indeed be confusing, which is why in the latest version I changed it to a Gui class which differs slightly from the current Window class. But I hadn't thought yet about having a Group inside the window/gui instead of inheriting from it. For the c++ version that is going to give complications as the whole callback system is build around these groups. Objects send their callback to their parent until it reaches the window. So if window wouldn't be a group, but would just contain a GroupObject then the callback would end up at that GroupObject, which has no idea on how to communicate with the window itself to alert the user of the callback. I don't want to go change the whole design again now to fix this, that might be for later. But I can always keep the c++ version in the way it is now and only make the change in the c# version. I'm not far enough in the c# version to find out whether there are going to be complications too (I can't think of any at the moment), but as the callback will be handled in a completely different way, I might actually be able to do it that way.
  3. Thanks for the fast responce. I already thought I would have to do something with interfaces. Making an object an interface won't be that easy though. It inherits from a class that comes from another library, so I would first have to break this inheritance. It's not that bad, but that would require some extra work. Also there is quite some code in Object itself which I don't want to write in every object seperately. The only problem I see with your idea from the first post is that Window isn't a GUIComponent but has to be like GUIContainer. GUIComponent has a 'pointer' to GUIContainer which could be either a panel or the window, and that's where the problem lies. Group could be made an interface, but then I would have a lot of code duplication: everything that is now in Group should be implemented inside GroupObject and Window in the same way. I could agree that Group could be the contract and that the others have to implement its functions, but the reason that I placed code in Group is because these functions would be implemented in exactly the same way in both GroupObject and Window. So if I live with a bit of code duplication then I can solve this, but I'm still looking for another way.
  4. I was trying to port my c++ gui to c# when I hit this issue. On one place I inherit from two base classes, which is apparently not possible in c#. Can anyone help me by suggesting a different design to work around this problem? Here are some more details: I have an Object class from which every widget inherits from. Then there is the Group class which is a container and has a list of objects. And then there is GroupObject. This is where the problem lies because it inherits from both Object and Group. It is used by classes like ChildWindow. These classes need to be drawable (the window treats child windows just like any other object) and they need to be containers (the child window will draw the widgets inside it, the window doesn't know and doesn't need to know what the child window contains). I cannot make Group an extension on Object, because the Window is a Group and not an Object (this is the only Group which isn't an Object). And the window has to inherit from Group because every Object has a pointer to its parent which can be either a GroupObject or the Window (so a Group pointer). Does anyone has a suggestion on how to change my design to make this work? If you need more information or if I wasn't clear enough about something, just ask. Thanks in advance
  5. I agree with Miklas that VS is still the best IDE for windows. When I changed to linux I coudn't use it anymore and I ended up using CodeBlocks, which I believe is the best choice if you want to go cross-platform. I personally prefer Xcode now, but I don't think you will be using that.
  6. Texus

    GUI behavior question

    The problem with that is that I can't change the SetScale function. My gui uses SFML and this is where SetScale function comes from. I could do that for all my own functions, but the problem would persist on SetScale, SetPosition, ... Thanks for sharing your thoughts anyway.
  7. Texus

    GUI behavior question

    What about this? - I could add a message box that would tell what went wrong. - After that I could add an assertion. When you are debugging then the program won't continue. - I can't quit the program from inside my gui so I'll just return an nullptr which will make the game crash. At least you already had an error telling that something went wrong. I can also add a define in my gui. If it is defined then my program gives message boxes and otherwise it will trow exceptions. Like this you can choose what you want.
  8. Texus

    GUI behavior question

    Unless you are planning on actually using the functionality that calling getObject("unknown_name") returns NULL[/quote] The GUI can be used by anybody, I don't know what other people plan to do. Maybe they will generate a dialog. I just don't like the try and catch thing. Why would someone have to write the following while on the other hand I could just work with boolean or NULL values? try { window.getObject("name"); } catch (exception& e) { // The function failed } I would have to write in my documentation that the function trows exceptions, while otherwise a person can look e.g. at the bool return value and immediately understand how the function works without checking the documentation. With a NULL pointer the person who uses my gui would have a choice: ignore that the function might return NULL and don't do the check, or check if the function failed or not. I know that not checking the return is a very bad way, but in this particular situation (with this function), you are usually 100% sure that the function will succeed. I know that this might sound like I am not listening to what you guys are saying and just do what I planned, but I just didn't look into it very closely. In a month or so I will investigate the options that you mentioned before I make any changes.
  9. Texus

    GUI behavior question

    I don't know why, but I just don't like the look of checked_ptr<Picture>, but this is indeed solved with a typedef. [color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]The more I think about this solution the better I find it. In most situations you don't need to store the pointer anyway so it doesn't really matter how it looks.[/font] [font=helvetica, arial, verdana, tahoma, sans-serif][color=#282828]I'll think about it for a while (I wasn't planning to change it during the first few weeks anyway).[/font] [color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]When I get enough time for it I will read some more information about smart pointers and find out what exception I could trow.[/font] [color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]Thanks again for your help.[/font]
  10. Texus

    GUI behavior question

    Thanks for your feedback. My knowledge on exceptions and smart-pointers is a little bit small, but this might be interesting for later. As far as I know, when doing this the user can no longer use a normal pointer: he has to use my smart pointer. I think that this makes it a little more complicated. I'd like to keep things easy so that people with almost no programming experience can still use my gui.
  11. Texus

    GUI behavior question

    Ok, thanks for your reply. If anyone else has an opinion then I would love to hear it.
  12. I know this is a long post, but I hope that someone is willing to read it and give my some advice with my problem. I have a quesion about how my GUI should respond in a certain situation. Here is an example code on how you can currently use my GUI. void init(tgui::Window& window) { tgui::Picture* picture = window.addPicture("pic1"); picture->load("filename.png"); picture->SetScale(3, 3); } int main() { tgui::Window window(...); init(window); window.getPicture("Pic1")->SetScale(2, 2); // <- this is the line I have a question about. // Other things } When you create an object you create and add them to the window with the addObject functions (addPicture, addButton, addCheckbox, ...). You will receive a pointer to the object so that you can load it, scale it, change it's position, ... You probably don't store the pointer and let it go out of scope, which is no problem. But when you need the pointer back (for e.g. changing the scale) then you will need to call a getObject function. To this function you must pass the name of the object, which is the same as the one that you passed to addObject. My question is, what do you think is best when you pass a wrong name (usually this can only occur when you made a typing mistake). - Should the function return a NULL pointer? This could be a good solution, but if you would do this: window.getObject("name")->SetScale(2, 2) when "name" would be wrong then you will get a segmentation fault. But when you would get that segfault you will know that you made a typo and you will find the problem easily. - The other option, the one that is currently used, isn't great either. On startup some empty objects will be created. When you pass a wrong name than the empty object is returned. You will not get a segfault, but the scaling won't have any effect. You will also get into problems when trying to call GetPosition(), because this will not return what you would expect. You might face some dificulties finding out why your object isn't scaled like you wanted. - Another option would be to return a boolean and take a reference as parameter. Then you will have to check if the function returns true, and if it does then you are allowed to change the object. But just like the first solution you will no longer be able to do window.getObject("name")->SetScale(2, 2). At first sight the third solutions look the best, but it will make the following code completely unusable: if (window.getCheckbox("check")->isChecked()) window.getLoadingbar("load")->incrementValue(); If I would still want the code I would have to write: tgui::Checkbox* checkbox; if (window.getCheckbox("check", checkbox)) { if (checkbox->isChecked()) { tgui::LoadingBar* loadingBar; if (window.getLoadingBar("load", loadingBar)) loadingBar->incrementValue(); } } I hope that it is clair that this isn't really what I want. I think changing to the first solution is the best thing to do, despite the fact that you might get segfaults if you mistype the name. Anyone has an opinion about it? Maybe a better solution? Thanks in advance.
  13. I was looking for information about GDI+ when I found the solution to my problem on this forum: http://www.daniweb.com/software-development/cpp/threads/189901. I tried the code and it worked on my old pc too. Next time I will however try to use GDI+ when I have to do something. Thanks again for your reply.
  14. I never used GDI+ before, but I don't have any objections to using it. I will try it and see if it works that way. Thanks for your help.
  15. I hope that this is the right forum to ask this question. I am trying to copy the screen and save it to a bmp file. The code does work, but not on a pc with 256 colors. I tested the code on my Windows 7 and it works correctly. When I tried this code on an older pc (Windows 2000) which has only desktop settings with 8-bit color, it failed. I don't get any errors, but the image is corrupted. (I think that the file is too small: 768 kB for an image of 1024x768) It is unimportant why, but I will not be able to debug the code on my older pc. The only way to find out if everything works is to use messageboxes. I have only tested one thing so far: cClrBits is 8 on my old pc. Does anyone know why the code isn't working? Are there perhaps functions in this code that don't work with 256 colors? Thanks in advance. // windows.h is included and _T(x) is defined here. // The function prototype of WriteBMPFile is also here. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { int Width = GetSystemMetrics(SM_CXSCREEN); int Height = GetSystemMetrics(SM_CYSCREEN); HDC ScreenDC = GetDC(NULL); HDC hDC = CreateCompatibleDC(ScreenDC); HBITMAP hBitmap = CreateCompatibleBitmap(ScreenDC, Width, Height); HBITMAP hOldBitmap = (HBITMAP)SelectObject(hDC, hBitmap); if ( ! BitBlt(hDC, 0, 0, Width, Height, ScreenDC, 0, 0, SRCCOPY)) MessageBox(NULL, _T("BitBlt failed."), _T("PRINSCREEN PROGRAM: Error"), 0); SelectObject(hDC, hOldBitmap); DeleteDC(hDC); ReleaseDC(NULL, ScreenDC); WriteBMPFile(hBitmap, _T("SCREENSHOT.BMP")); return 0; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void WriteBMPFile(HBITMAP bitmap, LPTSTR filename) { BITMAP bmp; PBITMAPINFO pbmi; WORD cClrBits; HANDLE hf; // file handle BITMAPFILEHEADER hdr; // bitmap file-header PBITMAPINFOHEADER pbih; // bitmap info-header LPBYTE lpBits; // memory pointer DWORD dwTotal; // total count of bytes DWORD cb; // incremental count of bytes BYTE *hp; // byte pointer DWORD dwTmp; // create the bitmapinfo header information if (!GetObject( bitmap, sizeof(BITMAP), (LPSTR)&bmp)) { MessageBox(NULL, _T("Could not retrieve bitmap info."), _T("PRINSCREEN PROGRAM: Error"), 0); return; } // Convert the color format to a count of bits. cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); if (cClrBits == 1) cClrBits = 1; else if (cClrBits <= 4) cClrBits = 4; else if (cClrBits <= 8) cClrBits = 8; else if (cClrBits <= 16) cClrBits = 16; else if (cClrBits <= 24) cClrBits = 24; else cClrBits = 32; // Allocate memory for the BITMAPINFO structure. if (cClrBits != 24) pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1<< cClrBits)); else pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER)); // Initialize the fields in the BITMAPINFO structure. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pbmi->bmiHeader.biWidth = bmp.bmWidth; pbmi->bmiHeader.biHeight = bmp.bmHeight; pbmi->bmiHeader.biPlanes = bmp.bmPlanes; pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; if (cClrBits < 24) pbmi->bmiHeader.biClrUsed = (1<<cClrBits); // If the bitmap is not compressed, set the BI_RGB flag. pbmi->bmiHeader.biCompression = BI_RGB; // Compute the number of bytes in the array of color // indices and store the result in biSizeImage. pbmi->bmiHeader.biSizeImage = (pbmi->bmiHeader.biWidth + 7) / 8 * pbmi->bmiHeader.biHeight * cClrBits; // Set biClrImportant to 0, indicating that all of the // device colors are important. pbmi->bmiHeader.biClrImportant = 0; // now open file and save the data pbih = (PBITMAPINFOHEADER) pbmi; lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage); if (!lpBits) { MessageBox(NULL, _T("Could not allocate memory."), _T("PRINSCREEN PROGRAM: Error"), 0); return; } HDC hDC = CreateCompatibleDC(NULL); // Retrieve the color table (RGBQUAD array) and the bits if (!GetDIBits(hDC, HBITMAP(bitmap), 0, (WORD) pbih->biHeight, lpBits, pbmi, DIB_RGB_COLORS)) // I also tested it with DIB_PAL_COLORS { MessageBox(NULL, _T("GetDIB error."), _T("PRINSCREEN PROGRAM: Error"), 0); return; } // Create the .BMP file. hf = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, (DWORD) 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL); if (hf == INVALID_HANDLE_VALUE) { MessageBox(NULL, _T("Could not create file for writing"), _T("Error"), 0); return; } hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M" // Compute the size of the entire file. hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + pbih->biSize + pbih->biClrUsed * sizeof(RGBQUAD) + pbih->biSizeImage); hdr.bfReserved1 = 0; hdr.bfReserved2 = 0; // Compute the offset to the array of color indices. hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + pbih->biSize + pbih->biClrUsed * sizeof (RGBQUAD); // Copy the BITMAPFILEHEADER into the .BMP file. if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), (LPDWORD) &dwTmp, NULL)) { MessageBox(NULL, _T("Could not write in to file (BITMAPFILEHEADER)."), _T("PRINSCREEN PROGRAM: Error"), 0); return; } // Copy the BITMAPINFOHEADER and RGBQUAD array into the file. if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) + pbih->biClrUsed * sizeof (RGBQUAD), (LPDWORD) &dwTmp, ( NULL))) { MessageBox(NULL, _T("Could not write in to file (BITMAPINFOHEADER and RGBQUAD)."), _T("PRINSCREEN PROGRAM: Error"), 0); return; } // Copy the array of color indices into the .BMP file. dwTotal = cb = pbih->biSizeImage; hp = lpBits; if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp, NULL)) { MessageBox(NULL, _T("Could not write in to file (array of color indices)."), _T("PRINSCREEN PROGRAM: Error"), 0); return; } // Close the .BMP file. if (!CloseHandle(hf)) { MessageBox(NULL, _T("Could not close file."), _T("PRINSCREEN PROGRAM: Error"), 0); return; } // Free memory. GlobalFree((HGLOBAL)lpBits); }
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!