I am trying to create a thread to continually update the time in the textbox. The issue is how do you reference a textbox in that was created in the main section of the program?

main.cpp

#include <windows.h>
#include <ctime>
#include "resource.h"

static bool keepRunning = true;
static HANDLE hThread = NULL;
static void run();
static void end();
static DWORD WINAPI ThreadTime(LPVOID lpParam);

extern char strCurrentTime[8];

HWND hWnd;
HINSTANCE hInst;
LRESULT CALLBACK DlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                       LPSTR lpCmdLine, int nCmdShow)
{
  DialogBox(hInstance, MAKEINTRESOURCE(IDD_CONTROLS_DLG), hWnd, 
              reinterpret_cast<DLGPROC>(DlgProc));

  hInst = hInstance;

  return 0;
}

LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{

  char strMeetingTime[8], strStartTime[8], strBreak1Start[8], strLunch[8], 
         strBreak2Start[8], strLeaveTime[8],  strLateBreak[8], strTime[10];

  HWND hWndCurrentTime, hWndMeetingTime, hWndStartTime, hWndBreak1, 
                hWndLunch, hWndBreak2, hWndLeaveTime, hWndLateBreak;

  hWndCurrentTime = GetDlgItem(hWndDlg, IDC_CURRENT_TIME);
  hWndMeetingTime = GetDlgItem(hWndDlg, IDC_MEETING_TIME);
  hWndStartTime   = GetDlgItem(hWndDlg, IDC_START_TIME);
  hWndBreak1      = GetDlgItem(hWndDlg, IDC_BREAK1);
  hWndLunch       = GetDlgItem(hWndDlg, IDC_LUNCH);
  hWndBreak2      = GetDlgItem(hWndDlg, IDC_BREAK2);
  hWndLeaveTime   = GetDlgItem(hWndDlg, IDC_LEAVE_TIME);
  hWndLateBreak   = GetDlgItem(hWndDlg, IDC_LATE_BREAK_BTN);

  switch(Msg)
  {
    case WM_INITDIALOG:
      run();  // start thread for showing current time
      SetWindowText(hWndMeetingTime, "");
      SetWindowText(hWndStartTime, "");
      SetWindowText(hWndBreak1, "");
      SetWindowText(hWndLunch, "");
      SetWindowText(hWndBreak2, "");
      SetWindowText(hWndLeaveTime, "");
    return TRUE;

    case WM_COMMAND:
      switch(wParam)
      {
        case IDC_LATE_BREAK_BTN:
          // Start a 15 minute timer

        return TRUE;

        case IDCANCEL:
          end();
          EndDialog(hWndDlg, 0);
        return TRUE;
      }
    break;
  }
        
  return FALSE;
}

static void run()
{
  DWORD dummy;
  hThread = CreateThread(NULL, 0, ThreadTime, NULL, 0, &dummy);
}

static void end()
{
  keepRunning = false;
}

static DWORD WINAPI ThreadTime(LPVOID lpParam)
{
  while(keepRunning)
  {
    time_t rawtime;
    struct tm * timeinfo;
    time( &rawtime);
    timeinfo = localtime ( &rawtime);
    strftime(strCurrentTime,80,"%I:%M:%S %p",timeinfo);
    SetWindowText(hWndCurrentTime, strCurrentTime);
    Sleep(1000);
  }
  return 0;
}

Recommended Answers

All 8 Replies

It has been my experience that windows can only be updated in the thread in which they are created. What I have done to resolve your problem is for thread2 to send a message to thread1 so that the window can be updated by thread1. See PostThreadMessage()

Try making hWndCurrentTime global. Then change strCurrentTime (in ThreadTime) temporarily to "xyz" and see if it displays. If not, then you'll need to do what AD suggests.

There is only one thread. The thread is used to continually run and to update the window in the main() section of the program. Also making hWndCurrentTime global does not work either. It actually still shows as undefined when running the thread.

This should probably be 80, not 8. extern char strCurrentTime[8];

8 is fine.. When I was testing it prior to the thread the 00:00:00 am/pm came in fine.

There is only one thread. The thread is used to continually run and to update the window in the main() section of the program. Also making hWndCurrentTime global does not work either. It actually still shows as undefined when running the thread.

>> hThread = CreateThread(NULL, 0, ThreadTime, NULL, 0, &dummy);

Nope, your program has two threads. The thread with winMain() is a thread and ThreadTime() is the second thread. Every windows program has at least one thread.

How can 8 be fine when the string you give in demonstration is 15 characters long? Also you're calling strftime with a maximum of 80. Making the hwnd global works for me:

#include <windows.h>
#include <ctime>
#include "resource.h"

static bool keepRunning = true;
static HANDLE hThread = NULL;
static void run();
static void end();
static DWORD WINAPI ThreadTime(LPVOID lpParam);

char strCurrentTime[80]; // change back to extern if needed

HWND hWndCurrentTime;
HWND hWnd;
HINSTANCE hInst;
LRESULT CALLBACK DlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                       LPSTR lpCmdLine, int nCmdShow)
{
  DialogBox(hInstance, MAKEINTRESOURCE(IDD_CONTROLS_DLG), hWnd,
              reinterpret_cast<DLGPROC>(DlgProc));

  hInst = hInstance;

  return 0;
}

LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{

//  char strMeetingTime[8], strStartTime[8], strBreak1Start[8], strLunch[8],
//         strBreak2Start[8], strLeaveTime[8],  strLateBreak[8], strTime[10];

//  HWND hWndMeetingTime, hWndStartTime, hWndBreak1,
//                hWndLunch, hWndBreak2, hWndLeaveTime, hWndLateBreak;

  hWndCurrentTime = GetDlgItem(hWndDlg, IDC_CURRENT_TIME);
/*  hWndMeetingTime = GetDlgItem(hWndDlg, IDC_MEETING_TIME);
  hWndStartTime   = GetDlgItem(hWndDlg, IDC_START_TIME);
  hWndBreak1      = GetDlgItem(hWndDlg, IDC_BREAK1);
  hWndLunch       = GetDlgItem(hWndDlg, IDC_LUNCH);
  hWndBreak2      = GetDlgItem(hWndDlg, IDC_BREAK2);
  hWndLeaveTime   = GetDlgItem(hWndDlg, IDC_LEAVE_TIME);
  hWndLateBreak   = GetDlgItem(hWndDlg, IDC_LATE_BREAK_BTN);*/

  switch(Msg)
  {
    case WM_INITDIALOG:
      run();  // start thread for showing current time
/*      SetWindowText(hWndMeetingTime, "");
      SetWindowText(hWndStartTime, "");
      SetWindowText(hWndBreak1, "");
      SetWindowText(hWndLunch, "");
      SetWindowText(hWndBreak2, "");
      SetWindowText(hWndLeaveTime, "");*/
    return TRUE;

    case WM_COMMAND:
      switch(wParam)
      {
//        case IDC_LATE_BREAK_BTN:
          // Start a 15 minute timer

//        return TRUE;

        case IDCANCEL:
          end();
          EndDialog(hWndDlg, 0);
        return TRUE;
      }
    break;
  }

  return FALSE;
}

static void run()
{
  DWORD dummy;
  hThread = CreateThread(NULL, 0, ThreadTime, NULL, 0, &dummy);
}

static void end()
{
  keepRunning = false;
}

static DWORD WINAPI ThreadTime(LPVOID lpParam)
{
  while(keepRunning)
  {
    time_t rawtime;
    struct tm * timeinfo;
    time( &rawtime);
    timeinfo = localtime ( &rawtime);
    strftime(strCurrentTime,80,"%I:%M:%S %p",timeinfo);
    SetWindowText(hWndCurrentTime, strCurrentTime);
    Sleep(1000);
  }
  return 0;
}

I am teaching myself C++ and using Dev-C++ as the debugger. I reduced the sizes to 15 and set all the char and hWnd variables with out extern and it worked. Thanks.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.