Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Thread

Thread

Scheduled Pinned Locked Moved C / C++ / MFC
debuggingquestioncareer
10 Posts 6 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • G Offline
    G Offline
    Gandilf
    wrote on last edited by
    #1

    Hi everyone, I have a little question about thread. I have read the faq and managed to program threads but now I'm facing a newbie challenge : I need to access to my dialog controls and the Document. I copy this code from this forum to access the Document from anywhere in my program. //Declaration static CTestSDIDoc * GetDoc(); //Implementation CTestSDIDoc * CTestSDIDoc::GetDoc() { CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd); return (CTestSDIDoc *) pFrame->GetActiveDocument(); } In my dialog (my own progress window with static text, a progress bar, 6 bitmaps and an OK button), I want to show a green check mark when a process has done is job. The process is created with CreateProcess method. The CreateProcess is writed in the TreadFunc of my dialog class. Before calling createprocess method, I must do some initialization in the Document so I must do this : metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); pDoc=CTestSDIDoc::GetDoc(); The bold text code works everywhere except in the TreadFunc method (I've got an assertion when running in debug mode). I want to know what Am I doing wrong ? Here my complete ThreadFunc function: UINT metprof::ThreadFunc(LPVOID pvParam) { metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); CString workingDirectory,strTemp,appArguments,strTemp2; pDoc=CTestSDIDoc::GetDoc(); TRACE("vis: %d\n",pDoc->m_VIS); workingDirectory=pDoc->m_modulesDirectory; workingDirectory.Insert(workingDirectory.GetLength(),"ATMOSPHERIC\\\\"); pDoc->m_SL_COND=1; appArguments=pDoc->m_dosPrompt; pDoc->createMetDataFile(); pDoc->createMetProfInputFiles(); STARTUPINFO siStartupInfo; PROCESS_INFORMATION piProcessInfo; memset(&siStartupInfo, 0, sizeof(siStartupInfo)); memset(&piProcessInfo, 0, sizeof(piProcessInfo)); siStartupInfo.cb = sizeof(siStartupInfo); strTemp2=pDoc->m_binDirectory; strTemp2.Replace("\\\\","\\"); strTemp2.Delete(strTemp2.GetLength()-1,1); strTemp.Format(" /c \"metprof.exe < metprof.rep -L -P \"%s\"\"",strTemp2); appArguments.Insert(appArguments.GetLength(),strTemp); char *str = appArguments.GetBuffer(appArguments.GetLength()); if(CreateProcess(NULL, // Application name str,//"cmd /c \"metprof.exe < metprof.rep -L\"",// Application arguments 0, 0, FALSE, CREATE_NO_WINDOW, 0, workingDirectory,//"C:\\Program Files\\Irblempkg\\IRBLEM4.1\\modules\\atmospheric\\", //

    A R J B D 5 Replies Last reply
    0
    • G Gandilf

      Hi everyone, I have a little question about thread. I have read the faq and managed to program threads but now I'm facing a newbie challenge : I need to access to my dialog controls and the Document. I copy this code from this forum to access the Document from anywhere in my program. //Declaration static CTestSDIDoc * GetDoc(); //Implementation CTestSDIDoc * CTestSDIDoc::GetDoc() { CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd); return (CTestSDIDoc *) pFrame->GetActiveDocument(); } In my dialog (my own progress window with static text, a progress bar, 6 bitmaps and an OK button), I want to show a green check mark when a process has done is job. The process is created with CreateProcess method. The CreateProcess is writed in the TreadFunc of my dialog class. Before calling createprocess method, I must do some initialization in the Document so I must do this : metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); pDoc=CTestSDIDoc::GetDoc(); The bold text code works everywhere except in the TreadFunc method (I've got an assertion when running in debug mode). I want to know what Am I doing wrong ? Here my complete ThreadFunc function: UINT metprof::ThreadFunc(LPVOID pvParam) { metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); CString workingDirectory,strTemp,appArguments,strTemp2; pDoc=CTestSDIDoc::GetDoc(); TRACE("vis: %d\n",pDoc->m_VIS); workingDirectory=pDoc->m_modulesDirectory; workingDirectory.Insert(workingDirectory.GetLength(),"ATMOSPHERIC\\\\"); pDoc->m_SL_COND=1; appArguments=pDoc->m_dosPrompt; pDoc->createMetDataFile(); pDoc->createMetProfInputFiles(); STARTUPINFO siStartupInfo; PROCESS_INFORMATION piProcessInfo; memset(&siStartupInfo, 0, sizeof(siStartupInfo)); memset(&piProcessInfo, 0, sizeof(piProcessInfo)); siStartupInfo.cb = sizeof(siStartupInfo); strTemp2=pDoc->m_binDirectory; strTemp2.Replace("\\\\","\\"); strTemp2.Delete(strTemp2.GetLength()-1,1); strTemp.Format(" /c \"metprof.exe < metprof.rep -L -P \"%s\"\"",strTemp2); appArguments.Insert(appArguments.GetLength(),strTemp); char *str = appArguments.GetBuffer(appArguments.GetLength()); if(CreateProcess(NULL, // Application name str,//"cmd /c \"metprof.exe < metprof.rep -L\"",// Application arguments 0, 0, FALSE, CREATE_NO_WINDOW, 0, workingDirectory,//"C:\\Program Files\\Irblempkg\\IRBLEM4.1\\modules\\atmospheric\\", //

      A Offline
      A Offline
      AlexO
      wrote on last edited by
      #2

      Yeah, you are missing the bold text :). Which part of the code does not work?

      A 1 Reply Last reply
      0
      • G Gandilf

        Hi everyone, I have a little question about thread. I have read the faq and managed to program threads but now I'm facing a newbie challenge : I need to access to my dialog controls and the Document. I copy this code from this forum to access the Document from anywhere in my program. //Declaration static CTestSDIDoc * GetDoc(); //Implementation CTestSDIDoc * CTestSDIDoc::GetDoc() { CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd); return (CTestSDIDoc *) pFrame->GetActiveDocument(); } In my dialog (my own progress window with static text, a progress bar, 6 bitmaps and an OK button), I want to show a green check mark when a process has done is job. The process is created with CreateProcess method. The CreateProcess is writed in the TreadFunc of my dialog class. Before calling createprocess method, I must do some initialization in the Document so I must do this : metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); pDoc=CTestSDIDoc::GetDoc(); The bold text code works everywhere except in the TreadFunc method (I've got an assertion when running in debug mode). I want to know what Am I doing wrong ? Here my complete ThreadFunc function: UINT metprof::ThreadFunc(LPVOID pvParam) { metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); CString workingDirectory,strTemp,appArguments,strTemp2; pDoc=CTestSDIDoc::GetDoc(); TRACE("vis: %d\n",pDoc->m_VIS); workingDirectory=pDoc->m_modulesDirectory; workingDirectory.Insert(workingDirectory.GetLength(),"ATMOSPHERIC\\\\"); pDoc->m_SL_COND=1; appArguments=pDoc->m_dosPrompt; pDoc->createMetDataFile(); pDoc->createMetProfInputFiles(); STARTUPINFO siStartupInfo; PROCESS_INFORMATION piProcessInfo; memset(&siStartupInfo, 0, sizeof(siStartupInfo)); memset(&piProcessInfo, 0, sizeof(piProcessInfo)); siStartupInfo.cb = sizeof(siStartupInfo); strTemp2=pDoc->m_binDirectory; strTemp2.Replace("\\\\","\\"); strTemp2.Delete(strTemp2.GetLength()-1,1); strTemp.Format(" /c \"metprof.exe < metprof.rep -L -P \"%s\"\"",strTemp2); appArguments.Insert(appArguments.GetLength(),strTemp); char *str = appArguments.GetBuffer(appArguments.GetLength()); if(CreateProcess(NULL, // Application name str,//"cmd /c \"metprof.exe < metprof.rep -L\"",// Application arguments 0, 0, FALSE, CREATE_NO_WINDOW, 0, workingDirectory,//"C:\\Program Files\\Irblempkg\\IRBLEM4.1\\modules\\atmospheric\\", //

        R Offline
        R Offline
        Ryan Binns
        wrote on last edited by
        #3

        You can't use MFC windows in multiple threads. Since CFrameWnd::GetActiveDocument() is MFC specific (not a Win32 function) you're pretty much screwed. You'll need to either pass the document as a parameter to your thread function, or find another way of doing it. MFC is just no good for applications where multiple threads manipulate the GUI. Ryan Being little and getting pushed around by big guys all my life I guess I compensate by pushing electrons and holes around. What a bully I am, but I do enjoy making subatomic particles hop at my bidding - Roger Wright (2nd April 2003, The Lounge)
        Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late - John Nichol "Point Of Impact"

        1 Reply Last reply
        0
        • A AlexO

          Yeah, you are missing the bold text :). Which part of the code does not work?

          A Offline
          A Offline
          AlexO
          wrote on last edited by
          #4

          Could you explain little bit more what is the following code does? metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); P.S. I assume "<" and ">" are lost due to the editor.

          G 1 Reply Last reply
          0
          • A AlexO

            Could you explain little bit more what is the following code does? metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); P.S. I assume "<" and ">" are lost due to the editor.

            G Offline
            G Offline
            Gandilf
            wrote on last edited by
            #5

            Hi AlexO, metprof *metProfPtr = static_cast<>(pvParam); CTestSDIDoc *pDoc = static_cast<>(pvParam); These are pointers to metProf dialog class to access dialog controls like editBox etc... The second one is a pointer too but to the Document. If I run my program, I got an assertion but if I click on ignore button the program continues to work correctly. Thanks for your help, Rene

            A 1 Reply Last reply
            0
            • G Gandilf

              Hi everyone, I have a little question about thread. I have read the faq and managed to program threads but now I'm facing a newbie challenge : I need to access to my dialog controls and the Document. I copy this code from this forum to access the Document from anywhere in my program. //Declaration static CTestSDIDoc * GetDoc(); //Implementation CTestSDIDoc * CTestSDIDoc::GetDoc() { CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd); return (CTestSDIDoc *) pFrame->GetActiveDocument(); } In my dialog (my own progress window with static text, a progress bar, 6 bitmaps and an OK button), I want to show a green check mark when a process has done is job. The process is created with CreateProcess method. The CreateProcess is writed in the TreadFunc of my dialog class. Before calling createprocess method, I must do some initialization in the Document so I must do this : metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); pDoc=CTestSDIDoc::GetDoc(); The bold text code works everywhere except in the TreadFunc method (I've got an assertion when running in debug mode). I want to know what Am I doing wrong ? Here my complete ThreadFunc function: UINT metprof::ThreadFunc(LPVOID pvParam) { metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); CString workingDirectory,strTemp,appArguments,strTemp2; pDoc=CTestSDIDoc::GetDoc(); TRACE("vis: %d\n",pDoc->m_VIS); workingDirectory=pDoc->m_modulesDirectory; workingDirectory.Insert(workingDirectory.GetLength(),"ATMOSPHERIC\\\\"); pDoc->m_SL_COND=1; appArguments=pDoc->m_dosPrompt; pDoc->createMetDataFile(); pDoc->createMetProfInputFiles(); STARTUPINFO siStartupInfo; PROCESS_INFORMATION piProcessInfo; memset(&siStartupInfo, 0, sizeof(siStartupInfo)); memset(&piProcessInfo, 0, sizeof(piProcessInfo)); siStartupInfo.cb = sizeof(siStartupInfo); strTemp2=pDoc->m_binDirectory; strTemp2.Replace("\\\\","\\"); strTemp2.Delete(strTemp2.GetLength()-1,1); strTemp.Format(" /c \"metprof.exe < metprof.rep -L -P \"%s\"\"",strTemp2); appArguments.Insert(appArguments.GetLength(),strTemp); char *str = appArguments.GetBuffer(appArguments.GetLength()); if(CreateProcess(NULL, // Application name str,//"cmd /c \"metprof.exe < metprof.rep -L\"",// Application arguments 0, 0, FALSE, CREATE_NO_WINDOW, 0, workingDirectory,//"C:\\Program Files\\Irblempkg\\IRBLEM4.1\\modules\\atmospheric\\", //

              J Offline
              J Offline
              Jonathan Craig
              wrote on last edited by
              #6

              Pass all the data the thread will need as the parameter:

              struct ThreadData
              {
              CTestSDIDoc *pDoc;
              metprof *metProfPtr;
              .
              . //Your data here.
              .
              HWND hWnd; //Pass CWnd objects by HWND.
              };

              .
              .
              .
              ThreadData *td = new ThreadData

              //Do this before starting thread.
              td.pDoc = CTestSDIDoc::GetDoc();
              td.metProfPtr = ... //Set this too.

              //Thread function must delete td!
              CWinThread *pThread = AfxBeginThread(ThreadProc, (LPVOID)td);
              .
              .
              .

              UINT ThreadProc(LPVOID lpParam)
              {
              ThreadData *td = (ThreadData *)lpParam;
              .
              . //Your code here.
              .
              delete td; //Delete memory so no leaks.
              return 0;
              }

              Also, you don't need a thread just to create a proccess. Hope this helps... :) Jonathan Craig www.mcw-tech.com

              J 1 Reply Last reply
              0
              • G Gandilf

                Hi AlexO, metprof *metProfPtr = static_cast<>(pvParam); CTestSDIDoc *pDoc = static_cast<>(pvParam); These are pointers to metProf dialog class to access dialog controls like editBox etc... The second one is a pointer too but to the Document. If I run my program, I got an assertion but if I click on ignore button the program continues to work correctly. Thanks for your help, Rene

                A Offline
                A Offline
                AlexO
                wrote on last edited by
                #7

                that is what I thought ... But it is the same pointer is it not? As for pointers, just an idea, would it not be safer to pass HWND of the dialog and use PostMessage for notification from the worker thread?

                1 Reply Last reply
                0
                • G Gandilf

                  Hi everyone, I have a little question about thread. I have read the faq and managed to program threads but now I'm facing a newbie challenge : I need to access to my dialog controls and the Document. I copy this code from this forum to access the Document from anywhere in my program. //Declaration static CTestSDIDoc * GetDoc(); //Implementation CTestSDIDoc * CTestSDIDoc::GetDoc() { CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd); return (CTestSDIDoc *) pFrame->GetActiveDocument(); } In my dialog (my own progress window with static text, a progress bar, 6 bitmaps and an OK button), I want to show a green check mark when a process has done is job. The process is created with CreateProcess method. The CreateProcess is writed in the TreadFunc of my dialog class. Before calling createprocess method, I must do some initialization in the Document so I must do this : metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); pDoc=CTestSDIDoc::GetDoc(); The bold text code works everywhere except in the TreadFunc method (I've got an assertion when running in debug mode). I want to know what Am I doing wrong ? Here my complete ThreadFunc function: UINT metprof::ThreadFunc(LPVOID pvParam) { metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); CString workingDirectory,strTemp,appArguments,strTemp2; pDoc=CTestSDIDoc::GetDoc(); TRACE("vis: %d\n",pDoc->m_VIS); workingDirectory=pDoc->m_modulesDirectory; workingDirectory.Insert(workingDirectory.GetLength(),"ATMOSPHERIC\\\\"); pDoc->m_SL_COND=1; appArguments=pDoc->m_dosPrompt; pDoc->createMetDataFile(); pDoc->createMetProfInputFiles(); STARTUPINFO siStartupInfo; PROCESS_INFORMATION piProcessInfo; memset(&siStartupInfo, 0, sizeof(siStartupInfo)); memset(&piProcessInfo, 0, sizeof(piProcessInfo)); siStartupInfo.cb = sizeof(siStartupInfo); strTemp2=pDoc->m_binDirectory; strTemp2.Replace("\\\\","\\"); strTemp2.Delete(strTemp2.GetLength()-1,1); strTemp.Format(" /c \"metprof.exe < metprof.rep -L -P \"%s\"\"",strTemp2); appArguments.Insert(appArguments.GetLength(),strTemp); char *str = appArguments.GetBuffer(appArguments.GetLength()); if(CreateProcess(NULL, // Application name str,//"cmd /c \"metprof.exe < metprof.rep -L\"",// Application arguments 0, 0, FALSE, CREATE_NO_WINDOW, 0, workingDirectory,//"C:\\Program Files\\Irblempkg\\IRBLEM4.1\\modules\\atmospheric\\", //

                  B Offline
                  B Offline
                  Brian Delahunty
                  wrote on last edited by
                  #8

                  Have a look at Jonathan Craig's post above this one. If that doesn't help drop me an email [click on the email button at the bottom of this post] and I'll help you out. Regards, Brian Dela :-)

                  1 Reply Last reply
                  0
                  • G Gandilf

                    Hi everyone, I have a little question about thread. I have read the faq and managed to program threads but now I'm facing a newbie challenge : I need to access to my dialog controls and the Document. I copy this code from this forum to access the Document from anywhere in my program. //Declaration static CTestSDIDoc * GetDoc(); //Implementation CTestSDIDoc * CTestSDIDoc::GetDoc() { CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd); return (CTestSDIDoc *) pFrame->GetActiveDocument(); } In my dialog (my own progress window with static text, a progress bar, 6 bitmaps and an OK button), I want to show a green check mark when a process has done is job. The process is created with CreateProcess method. The CreateProcess is writed in the TreadFunc of my dialog class. Before calling createprocess method, I must do some initialization in the Document so I must do this : metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); pDoc=CTestSDIDoc::GetDoc(); The bold text code works everywhere except in the TreadFunc method (I've got an assertion when running in debug mode). I want to know what Am I doing wrong ? Here my complete ThreadFunc function: UINT metprof::ThreadFunc(LPVOID pvParam) { metprof *metProfPtr = static_cast(pvParam); CTestSDIDoc *pDoc = static_cast(pvParam); CString workingDirectory,strTemp,appArguments,strTemp2; pDoc=CTestSDIDoc::GetDoc(); TRACE("vis: %d\n",pDoc->m_VIS); workingDirectory=pDoc->m_modulesDirectory; workingDirectory.Insert(workingDirectory.GetLength(),"ATMOSPHERIC\\\\"); pDoc->m_SL_COND=1; appArguments=pDoc->m_dosPrompt; pDoc->createMetDataFile(); pDoc->createMetProfInputFiles(); STARTUPINFO siStartupInfo; PROCESS_INFORMATION piProcessInfo; memset(&siStartupInfo, 0, sizeof(siStartupInfo)); memset(&piProcessInfo, 0, sizeof(piProcessInfo)); siStartupInfo.cb = sizeof(siStartupInfo); strTemp2=pDoc->m_binDirectory; strTemp2.Replace("\\\\","\\"); strTemp2.Delete(strTemp2.GetLength()-1,1); strTemp.Format(" /c \"metprof.exe < metprof.rep -L -P \"%s\"\"",strTemp2); appArguments.Insert(appArguments.GetLength(),strTemp); char *str = appArguments.GetBuffer(appArguments.GetLength()); if(CreateProcess(NULL, // Application name str,//"cmd /c \"metprof.exe < metprof.rep -L\"",// Application arguments 0, 0, FALSE, CREATE_NO_WINDOW, 0, workingDirectory,//"C:\\Program Files\\Irblempkg\\IRBLEM4.1\\modules\\atmospheric\\", //

                    D Offline
                    D Offline
                    David Crow
                    wrote on last edited by
                    #9

                    When the secondary thread finishes up a work unit, it simply needs to post a message to the primary thread (i.e., the one that owns the UI).

                    1 Reply Last reply
                    0
                    • J Jonathan Craig

                      Pass all the data the thread will need as the parameter:

                      struct ThreadData
                      {
                      CTestSDIDoc *pDoc;
                      metprof *metProfPtr;
                      .
                      . //Your data here.
                      .
                      HWND hWnd; //Pass CWnd objects by HWND.
                      };

                      .
                      .
                      .
                      ThreadData *td = new ThreadData

                      //Do this before starting thread.
                      td.pDoc = CTestSDIDoc::GetDoc();
                      td.metProfPtr = ... //Set this too.

                      //Thread function must delete td!
                      CWinThread *pThread = AfxBeginThread(ThreadProc, (LPVOID)td);
                      .
                      .
                      .

                      UINT ThreadProc(LPVOID lpParam)
                      {
                      ThreadData *td = (ThreadData *)lpParam;
                      .
                      . //Your code here.
                      .
                      delete td; //Delete memory so no leaks.
                      return 0;
                      }

                      Also, you don't need a thread just to create a proccess. Hope this helps... :) Jonathan Craig www.mcw-tech.com

                      J Offline
                      J Offline
                      Jonathan Craig
                      wrote on last edited by
                      #10

                      Gandilf emailed me: Your struct trick works perfectly but now I got an exception 0xC0000005 about metProfPtr. metProfPtr is a pointer to the current dialog (my own progress bar and bitmap, etc...). I need it to unhide one different bitmap at each process completion (total of processes: 6). When you talk about initializing pointer metprofPtr like td.pDoc = CTestSDIDoc::GetDoc(); for pDoc, what can I do ? (td.metProfPtr = 0 ?) Maybe you have another suggestion. Thanks a lot, Rene There are two different ways to do it. 1.) Add the pointer to the dialog to the ThreadData struct.

                      struct ThreadData
                      {
                      .
                      CMyDialog *pDlg;
                      .
                      };

                      td.pDlg = this;

                      This may or may not cause problems when calling methods on td->pDlg. 2.) If you know which object you wish to hide or show, you can pass a HWND handle to it. If your bitmap object is a CStatic.

                      struct ThreadData
                      {
                      .
                      HWND hWnd;
                      .
                      };

                      td.hWnd = m_bitmap.GetSafeHwnd();

                      In your thread you would call.

                      ::ShowWindow(td->hWnd, SW_HIDE);

                      or

                      ::ShowWindow(td->hWnd, SW_SHOW);

                      This is the correct way to pass window objects to a thread. Good Luck :) Jonathan Craig www.mcw-tech.com

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups