How can I theme a module in Drupal 7? I'm new to developing in Drupal and am trying to create my first module. I've got it all set up, but I don't know how to add the theme to it. Right now it just shows a blank page with only the text "Hello World".

   &lt;?php
function news_main() {  
    require_once('/global_applications/news/home.php');
}

function news_menu() {
    $items = array();

    $items['news'] = array(
        'page callback' =&gt; 'news_main',
        'access arguments' =&gt; array('access content'),
        'type' =&gt; MENU_CALLBACK,
     );

    return $items;
}
?&gt;
You are seeing a page containing just that string because the code you are using is printing the string, and then it exits. This means the theming system used by Drupal is not used to render the page, which will just contain the echoed text.

If you want to theme a page, the page callback needs to return HTML content, as in Drupal 6, or an array that contains the same elements used for the array passed to drupal_render().

As example of page callback, you can look at node_add_page():

function node_add_page() {
  $item = menu_get_item();
  $content = system_admin_menu_block($item);
  // Bypass the node/add listing if only one content type is available.
  if (count($content) == 1) {
    $item = array_shift($content);
    drupal_goto($item['href']);
  }
  return theme('node_add_list', array('content' =&gt; $content));
}


An example of page callback that returns an array is node_page_default(), which contains the following code:

function node_page_default() {
  $select = db_select('node', 'n')
    -&gt;fields('n', array('nid', 'sticky', 'created'))
    -&gt;condition('promote', 1)
    -&gt;condition('status', 1)
    -&gt;orderBy('sticky', 'DESC')
    -&gt;orderBy('created', 'DESC')
    -&gt;extend('PagerDefault')
    -&gt;limit(variable_get('default_nodes_main', 10))
    -&gt;addTag('node_access');

  $nids = $select-&gt;execute()-&gt;fetchCol();

  if (!empty($nids)) {
    $nodes = node_load_multiple($nids);
    $build = node_view_multiple($nodes);

    // 'rss.xml' is a path, not a file, registered in node_menu().
    drupal_add_feed('rss.xml', variable_get('site_name', 'Drupal') . ' ' . t('RSS'));
    $build['pager'] = array(
      '#theme' =&gt; 'pager', 
      '#weight' =&gt; 5,
    );
    drupal_set_title('');
  }
  else {
    drupal_set_title(t('Welcome to @site-name', array('@site-name' =&gt; variable_get('site_name', 'Drupal'))), PASS_THROUGH);

    $default_message = '&lt;p&gt;' . t('No front page content has been created yet.') . '&lt;/p&gt;';

    $default_links = array();
    if (_node_add_access()) {
      $default_links[] = l(t('Add new content'), 'node/add');
    }
    if (!empty($default_links)) {
      $default_message .= theme('item_list', array('items' =&gt; $default_links));
    }

    $build['default_message'] = array(
      '#markup' =&gt; $default_message, 
      '#prefix' =&gt; '&lt;div id="first-time"&gt;', 
      '#suffix' =&gt; '&lt;/div&gt;',
    );
  }
  return $build;
}


You first task is then to incorporate the code there is in the /global_applications/news/home.php file into news_main(), and change it to either return HTML content, or an array as required by drupal_render(). The latter is preferred as it allows other modules to alter the output of the page callback.

Keep in mind that if you need to render a form, you should use the form API, which means that the page callback should be "drupal_get_form," in that case; the first argument passed in "page arguments" is the form ID for the form to render.